qec-code 0.3.0

Rust primitives for constructing and analyzing quantum error-correcting codes
Documentation
use qec_code::QecError;
use qec_code::regular_classical::{
    REGULAR_CLASSICAL_MATRIX_ALGORITHM_V1, RegularClassicalMatrixConfig, SplitMix64V1,
    bounded_index_v1, deterministic_regular_matrix,
};

fn fixture_config(seed: u64) -> RegularClassicalMatrixConfig {
    RegularClassicalMatrixConfig {
        column_count: 6,
        row_count: 4,
        column_weight: 2,
        row_weight: 3,
        seed,
        algorithm_version: REGULAR_CLASSICAL_MATRIX_ALGORITHM_V1,
        retry_limit: 16,
    }
}

fn assert_regular_degrees(
    rows: &[Vec<usize>],
    column_count: usize,
    row_count: usize,
    row_weight: usize,
    column_weight: usize,
) {
    assert_eq!(rows.len(), row_count);
    let mut column_degrees = vec![0; column_count];
    for row in rows {
        assert_eq!(row.len(), row_weight);
        let mut sorted = row.clone();
        sorted.sort_unstable();
        assert_eq!(&sorted, row);
        for &column in row {
            assert!(column < column_count);
            column_degrees[column] += 1;
        }
    }
    assert_eq!(column_degrees, vec![column_weight; column_count]);
}

#[test]
fn deterministic_regular_matrix_matches_v1_fixture() {
    let first = deterministic_regular_matrix(fixture_config(7)).unwrap();
    let second = deterministic_regular_matrix(fixture_config(7)).unwrap();
    assert_eq!(first, second);
    assert_eq!(
        first,
        vec![
            vec![0, 1, 2],
            vec![0, 3, 4],
            vec![1, 3, 5],
            vec![2, 4, 5],
        ]
    );
    assert_regular_degrees(&first, 6, 4, 3, 2);

    let seed8 = deterministic_regular_matrix(fixture_config(8)).unwrap();
    assert_ne!(seed8, first);
    assert_regular_degrees(&seed8, 6, 4, 3, 2);
}

#[test]
fn deterministic_regular_matrix_rejects_invalid_degrees() {
    let mut config = fixture_config(7);
    config.column_count = 0;
    assert!(matches!(
        deterministic_regular_matrix(config),
        Err(QecError::InvalidRegularClassicalMatrixConfig {
            option: "column_count",
            ..
        })
    ));

    let mut config = fixture_config(7);
    config.row_count = 0;
    assert!(matches!(
        deterministic_regular_matrix(config),
        Err(QecError::InvalidRegularClassicalMatrixConfig {
            option: "row_count",
            ..
        })
    ));

    let mut config = fixture_config(7);
    config.column_weight = 0;
    assert!(matches!(
        deterministic_regular_matrix(config),
        Err(QecError::InvalidRegularClassicalMatrixConfig {
            option: "column_weight",
            ..
        })
    ));

    let mut config = fixture_config(7);
    config.row_weight = 0;
    assert!(matches!(
        deterministic_regular_matrix(config),
        Err(QecError::InvalidRegularClassicalMatrixConfig {
            option: "row_weight",
            ..
        })
    ));

    let mut config = fixture_config(7);
    config.retry_limit = 0;
    assert!(matches!(
        deterministic_regular_matrix(config),
        Err(QecError::InvalidRegularClassicalMatrixConfig {
            option: "retry_limit",
            ..
        })
    ));

    let mut config = fixture_config(7);
    config.algorithm_version = 2;
    assert!(matches!(
        deterministic_regular_matrix(config),
        Err(QecError::UnsupportedRegularClassicalMatrixAlgorithm {
            algorithm_version: 2
        })
    ));

    let mut config = fixture_config(7);
    config.row_count = 1;
    assert!(matches!(
        deterministic_regular_matrix(config),
        Err(QecError::InvalidRegularClassicalMatrixConfig {
            option: "column_weight",
            ..
        })
    ));

    let mut config = fixture_config(7);
    config.column_count = 2;
    assert!(matches!(
        deterministic_regular_matrix(config),
        Err(QecError::InvalidRegularClassicalMatrixConfig {
            option: "row_weight",
            ..
        })
    ));

    let mut config = fixture_config(7);
    config.column_count = 5;
    assert!(matches!(
        deterministic_regular_matrix(config),
        Err(QecError::RegularClassicalMatrixStubCountMismatch {
            column_stubs: 10,
            row_stubs: 12,
        })
    ));

    let mut config = fixture_config(7);
    config.column_count = usize::MAX;
    assert!(matches!(
        deterministic_regular_matrix(config),
        Err(QecError::RegularClassicalMatrixStubCountOverflow { side: "column" })
    ));
}

#[test]
fn splitmix64_v1_seed7_matches_golden_words() {
    let mut stream = SplitMix64V1::new(7);
    let words = (0..8).map(|_| stream.next_u64()).collect::<Vec<_>>();
    assert_eq!(
        words,
        vec![
            0x63CBE1E459320DD7,
            0x044C3CD7F43C661C,
            0xE6984080BAB12A02,
            0x953AEB70673E29CB,
            0x73D33B666A1E21DA,
            0x3FDABE86CBBEAA11,
            0x77CBC4A133C2D0F6,
            0x53FCD6513D02BEFE,
        ]
    );

    let mut zero_bound_stream = SplitMix64V1::new(7);
    assert_eq!(bounded_index_v1(&mut zero_bound_stream, 0), None);
    assert_eq!(zero_bound_stream.state(), 7);

    let mut bounded = SplitMix64V1::new(7);
    let values = (0..8)
        .map(|_| bounded_index_v1(&mut bounded, 10).unwrap())
        .collect::<Vec<_>>();
    assert_eq!(values, vec![7, 4, 6, 3, 4, 5, 8, 2]);

    let mut rejection = SplitMix64V1::new(7);
    assert_eq!(
        bounded_index_v1(&mut rejection, (1u64 << 63) + 1),
        Some(7_392_729_709_960_833_537)
    );
}

#[test]
fn deterministic_regular_matrix_retry_limit_one_returns_exhausted() {
    let config = RegularClassicalMatrixConfig {
        column_count: 3,
        row_count: 3,
        column_weight: 2,
        row_weight: 2,
        seed: 1,
        algorithm_version: REGULAR_CLASSICAL_MATRIX_ALGORITHM_V1,
        retry_limit: 1,
    };

    assert!(matches!(
        deterministic_regular_matrix(config),
        Err(QecError::RegularClassicalMatrixGenerationExhausted {
            retry_limit: 1,
            attempts: 1,
            ..
        })
    ));
}