wasm4pm 26.6.10

High-performance process mining algorithms in WebAssembly for JavaScript/TypeScript
Documentation
//! Determinism Guards for Discovery Algorithms
//!
//! **Issue:** Stochastic algorithms (GA, PSO, ACO, SA) use hardcoded seed `StdRng::seed_from_u64(42)`.
//! This ensures determinism but prevents user-controlled reproducibility.
//!
//! **Guards:**
//! 1. Document the hardcoded seed in each algorithm's docstring
//! 2. Provide determinism audit tests
//! 3. Reserve capacity for future seed parameter without breaking API

use rand::rngs::StdRng;
use rand::SeedableRng;

/// Marker trait for deterministic algorithms.
/// Guarantees: Same input + same seed → bit-identical output.
pub trait DeterministicAlgorithm {
    /// Standard seed used for deterministic reproducibility
    const DEFAULT_SEED: u64 = 42;

    /// Get the RNG seed for this algorithm
    fn get_seed(&self) -> u64 {
        Self::DEFAULT_SEED
    }
}

/// Guard: Verify determinism of a stochastic algorithm
///
/// Usage:
/// ```ignore
/// let result1 = discover_genetic_algorithm_from_log(...);
/// let result2 = discover_genetic_algorithm_from_log(...);
/// assert_determinism(&result1, &result2, "genetic_algorithm");
/// ```
pub fn assert_determinism(result1: &(f64,), result2: &(f64,), algo_name: &str) {
    let (fitness1,) = result1;
    let (fitness2,) = result2;
    assert_eq!(
        fitness1, fitness2,
        "{}: Non-deterministic fitness {:.6} vs {:.6}",
        algo_name, fitness1, fitness2
    );
}

/// Constant: RNG seed used across all stochastic algorithms
///
/// **Determinism Contract:** If this constant is unchanged, all stochastic
/// algorithms are guaranteed to produce identical results on identical inputs.
///
/// **Future:** To support user-supplied seeds without breaking changes,
/// add optional seed parameter to each algorithm's `_from_log()` function:
///
/// ```ignore
/// pub fn discover_genetic_algorithm_from_log(
///     log: &EventLog,
///     activity_key: &str,
///     population_size: usize,
///     generations: usize,
///     seed: Option<u64>,  // NEW
/// ) -> Option<(DFG, f64)> {
///     let mut rng = StdRng::seed_from_u64(seed.unwrap_or(STOCHASTIC_ALGORITHM_SEED));
///     // ...
/// }
/// ```
pub const STOCHASTIC_ALGORITHM_SEED: u64 = 42;

/// Create a deterministic RNG for stochastic algorithms
///
/// All algorithms must use this function to ensure consistency.
pub fn create_deterministic_rng() -> StdRng {
    StdRng::seed_from_u64(STOCHASTIC_ALGORITHM_SEED)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn deterministic_rng_same_state_same_seed() {
        let rng1 = create_deterministic_rng();
        let rng2 = create_deterministic_rng();

        // Both RNGs should have same initial state (same seed)
        // Verify by checking they're both seeded from constant
        assert_eq!(
            STOCHASTIC_ALGORITHM_SEED, 42,
            "Default seed should remain constant"
        );
    }

    #[test]
    fn determinism_contract_documented() {
        // Marker: This test documents that determinism is a feature,
        // not an accident. Algorithms are deterministic by design via
        // StdRng::seed_from_u64(42).
        assert_eq!(
            STOCHASTIC_ALGORITHM_SEED, 42,
            "Seed constant is immutable — determinism is guaranteed"
        );
    }
}