Liking cljdoc? Tell your friends :D

Universal Automaton Transposition Implementation - Phase 1 Complete

Date: 2025-11-13 Status: Phase 1 COMPLETE, Phase 2 IN PROGRESS

Objective

Implement transposition and merge/split operations for UniversalAutomaton to unblock GeneralizedAutomaton Phase 2d.

What Was Completed (Phase 1)

1. Position Variant Infrastructure ✅

Changes to PositionVariant trait (position.rs:87-103):

pub trait PositionVariant: Clone + fmt::Debug + PartialEq + Eq + std::hash::Hash {
    /// State type for this variant
    type State: Clone + fmt::Debug + PartialEq + Eq + std::hash::Hash + Default;

    fn variant_name() -> &'static str;
}

Key Achievement: Added State associated type to allow variants to track additional state.

2. Variant State Types ✅

TranspositionState (position.rs:119-133):

#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
pub enum TranspositionState {
    #[default]
    Usual,        // Regular position i#e
    Transposing,  // Transposition state i#e_t
}

MergeSplitState (position.rs:151-165):

#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
pub enum MergeSplitState {
    #[default]
    Usual,       // Regular position i#e
    Splitting,   // Split state i#e_s
}

Variant Implementations:

  • Standard: type State = () (zero-sized, no overhead)
  • Transposition: type State = TranspositionState
  • MergeAndSplit: type State = MergeSplitState

3. UniversalPosition Refactoring ✅

Updated enum (position.rs:197-233):

pub enum UniversalPosition<V: PositionVariant> {
    INonFinal {
        offset: i32,
        errors: u8,
        variant_state: V::State,  // Was: variant: PhantomData<V>
    },
    MFinal {
        offset: i32,
        errors: u8,
        variant_state: V::State,
    },
}

API Changes:

  • Removed PhantomData<V>
  • Added variant_state: V::State field
  • Updated constructors to use V::State::default()

4. New Constructor Methods ✅

With custom variant state (position.rs:350-431):

pub fn new_i_with_state(
    offset: i32,
    errors: u8,
    max_distance: u8,
    variant_state: V::State,
) -> Result<Self, PositionError>

pub fn new_m_with_state(
    offset: i32,
    errors: u8,
    max_distance: u8,
    variant_state: V::State,
) -> Result<Self, PositionError>

Accessor method:

pub fn variant_state(&self) -> &V::State

5. Test Results ✅

All 156 Universal automaton tests pass:

$ cargo test --lib universal
test result: ok. 156 passed; 0 failed; 0 ignored; 0 measured

Backward Compatibility: Fully maintained for Standard variant (zero-size state).

What Remains (Phase 2-4)

Phase 2: Implement Transposition Successor Logic

Goal: Add transposition-specific successor generation

Approach: Specialize successors() method for Transposition variant

From Mitankin's Thesis (Definition 7, Page 16):

For regular positions i#e (Usual state):

δ^D,t_e(i#e, b) = δ^D,ε_e(i#e, b) ∪ {
    {(i+1)#(e+1)_t}  if b[1] = 0 ∧ e < n  (enter transposition state)
}

For transposition state i#e_t (Transposing):

δ^D,t_e(i#e_t, b) = {
    {(i+2)#e}        if b[1] = 1  (complete transposition - chars swapped)
    ∅                otherwise     (transposition failed)
}

Implementation Strategy:

impl UniversalPosition<Transposition> {
    pub fn successors(
        &self,
        bit_vector: &CharacteristicVector,
        max_distance: u8,
    ) -> Vec<Self> {
        match self {
            Self::INonFinal { offset, errors, variant_state } => {
                match variant_state {
                    TranspositionState::Usual => {
                        // 1. Get standard successors
                        let mut successors = Self::successors_i_type_standard(...);

                        // 2. Add transposition initiation if no match
                        let match_index = (max_distance as i32 + offset) as usize;
                        if match_index < bit_vector.len()
                            && !bit_vector.is_match(match_index)
                            && errors < max_distance
                        {
                            // Enter transposition state: (i+1)#(e+1)_t
                            if let Ok(trans) = Self::new_i_with_state(
                                offset + 1,
                                errors + 1,
                                max_distance,
                                TranspositionState::Transposing
                            ) {
                                successors.push(trans);
                            }
                        }

                        successors
                    }

                    TranspositionState::Transposing => {
                        // In transposition state: check if next char matches previous
                        let match_index = (max_distance as i32 + offset) as usize;

                        if match_index < bit_vector.len()
                            && bit_vector.is_match(match_index)
                        {
                            // Complete transposition: (i+2)#e
                            vec![Self::new_i_with_state(
                                offset + 1,  // I^ε: (i+2)#e → I+(i+1)#e
                                errors,
                                max_distance,
                                TranspositionState::Usual
                            ).ok().into_iter().collect()]
                        } else {
                            // Transposition failed
                            vec![]
                        }
                    }
                }
            }
            Self::MFinal { ... } => {
                // Similar logic for M-type
                ...
            }
        }
    }
}

Challenge: Need to handle conversion from standard successors (which have () state) to transposition successors (which need TranspositionState).

Solution: Use generic helpers or match on variant type when creating successors.

Phase 3: Implement Merge/Split Successor Logic

Similar to transposition, but for merge and split operations.

Phase 4: Add Tests

Transposition Tests:

#[test]
fn test_transposition_adjacent_swap() {
    let automaton = UniversalAutomaton::<Transposition>::new(2);
    assert!(automaton.accepts("test", "etst"));  // swap 't' and 'e'
    assert!(automaton.accepts("test", "tset"));  // swap 'e' and 's'
}

#[test]
fn test_transposition_state_transition() {
    // Test entering and exiting transposition state
    let pos = UniversalPosition::<Transposition>::new_i(0, 0, 2).unwrap();
    // ... verify state transitions
}

Technical Challenges Identified

1. Successor Method Dispatch

Problem: Current successors() is generic over V: PositionVariant but needs variant-specific logic.

Options:

  • A: Use trait methods on PositionVariant to compute successors
  • B: Implement separate successors() for each variant via impl UniversalPosition<Transposition>
  • C: Use match on variant_state inside generic method

Recommendation: Option B - clearest separation of concerns.

2. Standard Successor Reuse

Problem: Transposition needs to include standard successors plus transposition-specific ones.

Solution: Make successors_i_type_standard() and successors_m_type_standard() create positions with generic state, then convert.

3. Display Format

Question: How to display transposition state?

Answer: Extend Display to show state: I + 0#1_t for transposition state.

Files Modified

  1. src/transducer/universal/position.rs
    • Lines 87-103: Added State associated type to PositionVariant
    • Lines 111-117: Updated Standard implementation
    • Lines 119-149: Added TranspositionState and Transposition implementation
    • Lines 151-179: Added MergeSplitState and MergeAndSplit implementation
    • Lines 197-233: Updated UniversalPosition enum structure
    • Lines 301-305: Updated new_i() constructor
    • Lines 343-347: Updated new_m() constructor
    • Lines 350-431: Added new_i_with_state() and new_m_with_state() constructors
    • Lines 440-445: Added variant_state() accessor

Documentation Created

  1. docs/universal/transposition_implementation_plan.md - Full implementation plan
  2. docs/universal/transposition_phase1_complete.md - This document

Next Steps

To complete transposition implementation:

  1. Implement successors() for Transposition variant (~2-3 hours)

    • Add impl UniversalPosition<Transposition> block
    • Implement I-type transposition logic
    • Implement M-type transposition logic
  2. Add transposition tests (~1 hour)

    • Basic transposition tests
    • State transition tests
    • Cross-validation with examples
  3. Implement merge/split (~2-3 hours)

    • Similar structure to transposition
    • Add tests
  4. Update GeneralizedAutomaton (~2 hours)

    • Use UniversalAutomaton as reference
    • Implement multi-char operations
    • Cross-validate

Total Remaining Time: ~7-9 hours

API Breaking Changes Summary

What Changed:

  • UniversalPosition now has variant_state: V::State instead of variant: PhantomData<V>
  • Added new constructor methods new_i_with_state() and new_m_with_state()
  • Added variant_state() accessor

Impact:

  • ✅ All existing tests pass
  • ✅ Standard variant has zero overhead (() is zero-sized)
  • ✅ API is more flexible and can track variant-specific state
  • ⚠️ Breaking change, but acceptable since Universal automaton hasn't been published

Mitigation:

  • Existing code using Standard variant works unchanged
  • Default constructors (new_i, new_m) still work the same way
  • Only code that pattern matches on position internals needs updates

Success Criteria

Phase 1 (Complete):

  • [x] Added State associated type to PositionVariant
  • [x] Defined TranspositionState and MergeSplitState enums
  • [x] Updated UniversalPosition to store variant state
  • [x] Updated constructors
  • [x] All 156 tests pass
  • [x] Zero overhead for Standard variant

Phase 2 (Next):

  • [ ] Implement transposition successor logic
  • [ ] Add transposition tests
  • [ ] Verify against thesis examples

Phase 3 (Future):

  • [ ] Implement merge/split successor logic
  • [ ] Add merge/split tests

Phase 4 (Future):

  • [ ] Update GeneralizedAutomaton with transposition support
  • [ ] Cross-validate implementations
  • [ ] Performance benchmarking

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close