qec-code 0.3.0

Rust primitives for constructing and analyzing quantum error-correcting codes
Documentation
#![cfg(feature = "cli")]

use std::path::{Path, PathBuf};

use clap::Parser;
use qec_code::QecError;
use qec_code::cli::{Cli, CssMatrixKind, run};
use qec_code::css::{CssCode, SparseRowsMatrix};
use qec_code::distance::compute_distance;
use qec_code::family_contract::{
    CssFamilySpec, RequestedFamilyId, ShorLikeSpec, construct_css, parse_css_construction_json,
    verify_css_orthogonality,
};
use tempfile::tempdir;

fn assert_canonical_sparse_rows(rows: &[Vec<usize>]) {
    for row in rows {
        assert!(
            row.windows(2).all(|window| window[0] < window[1]),
            "row must contain sorted unique supports: {row:?}"
        );
    }
}

fn css_code_from_result(result: &qec_code::family_contract::CssConstructionResult) -> CssCode {
    let hx = SparseRowsMatrix::new(result.stats.n, result.checks.h_x.clone())
        .unwrap()
        .to_dense_rows();
    let hz = SparseRowsMatrix::new(result.stats.n, result.checks.h_z.clone())
        .unwrap()
        .to_dense_rows();
    CssCode::from_hx_hz(hx, hz).unwrap()
}

fn write_spec(dir: &Path, name: &str, body: &str) -> PathBuf {
    let path = dir.join(name);
    std::fs::write(&path, body).expect("spec should be writable");
    path
}

fn cli_export_from_spec(spec: PathBuf, matrix: CssMatrixKind) -> String {
    let matrix = match matrix {
        CssMatrixKind::Hx => "hx",
        CssMatrixKind::Hz => "hz",
    };
    run(Cli::parse_from([
        "qec-code",
        "code",
        "css",
        "construct",
        "--spec",
        spec.to_str().expect("spec path should be UTF-8"),
        matrix,
    ]))
    .unwrap()
}

#[test]
fn shor_like_3x3_matches_fixture() {
    let expected_hx = vec![vec![0, 1, 2, 3, 4, 5], vec![3, 4, 5, 6, 7, 8]];
    let expected_hz = vec![
        vec![0, 1],
        vec![1, 2],
        vec![3, 4],
        vec![4, 5],
        vec![6, 7],
        vec![7, 8],
    ];
    let result = construct_css(
        CssFamilySpec::ShorLike(ShorLikeSpec {
            outer_blocks: 3,
            inner_block: 3,
        })
        .into(),
    )
    .unwrap();

    assert_eq!(result.schema_version, 1);
    assert_eq!(result.construction_id, "shor_like");
    assert_eq!(
        result.requested_family_id,
        Some(RequestedFamilyId::ShorLike)
    );
    assert_eq!(
        result.normalized_parameters["outer_blocks"],
        serde_json::json!(3)
    );
    assert_eq!(
        result.normalized_parameters["inner_block"],
        serde_json::json!(3)
    );
    assert_eq!(result.stats.n, 9);
    assert_eq!(result.stats.m_x, 2);
    assert_eq!(result.stats.m_z, 6);
    assert_eq!(result.stats.rank_x, 2);
    assert_eq!(result.stats.rank_z, 6);
    assert_eq!(result.stats.k, 1);
    assert_eq!(result.stats.d_x, Some(3));
    assert_eq!(result.stats.d_z, Some(3));
    assert_eq!(result.stats.d_x.unwrap().min(result.stats.d_z.unwrap()), 3);
    assert_eq!(result.checks.h_x, expected_hx);
    assert_eq!(result.checks.h_z, expected_hz);
    assert_canonical_sparse_rows(&result.checks.h_x);
    assert_canonical_sparse_rows(&result.checks.h_z);
    verify_css_orthogonality(result.stats.n, &result.checks.h_x, &result.checks.h_z).unwrap();
    assert_eq!(
        compute_distance(css_code_from_result(&result).code())
            .unwrap()
            .distance,
        3
    );

    let parsed = parse_css_construction_json(
        r#"{"schema_version":1,"construction":"shor_like","outer_blocks":3,"inner_block":3}"#,
    )
    .unwrap();
    assert_eq!(
        parsed,
        CssFamilySpec::ShorLike(ShorLikeSpec {
            outer_blocks: 3,
            inner_block: 3,
        })
        .into()
    );
    let repeated = construct_css(parsed).unwrap();
    assert_eq!(
        serde_json::to_string(&result).unwrap(),
        serde_json::to_string(&repeated).unwrap()
    );

    let dir = tempdir().unwrap();
    let spec_path = write_spec(
        dir.path(),
        "shor-like-3x3.json",
        r#"{"schema_version":1,"construction":"shor_like","outer_blocks":3,"inner_block":3}"#,
    );
    let cli_hx = cli_export_from_spec(spec_path, CssMatrixKind::Hx);
    assert_eq!(
        cli_hx,
        SparseRowsMatrix::new(result.stats.n, result.checks.h_x.clone())
            .unwrap()
            .to_json_string()
    );
}

#[test]
fn shor_like_rectangular_3x4_has_expected_parameters() {
    let result = construct_css(
        CssFamilySpec::ShorLike(ShorLikeSpec {
            outer_blocks: 3,
            inner_block: 4,
        })
        .into(),
    )
    .unwrap();

    assert_eq!(result.construction_id, "shor_like");
    assert_eq!(
        result.requested_family_id,
        Some(RequestedFamilyId::ShorLike)
    );
    assert_eq!(result.stats.n, 12);
    assert_eq!(result.stats.m_x, 2);
    assert_eq!(result.stats.m_z, 9);
    assert_eq!(result.stats.rank_x, 2);
    assert_eq!(result.stats.rank_z, 9);
    assert_eq!(result.stats.k, 1);
    assert_eq!(result.stats.d_x, Some(4));
    assert_eq!(result.stats.d_z, Some(3));
    assert_eq!(result.stats.d_x.unwrap().min(result.stats.d_z.unwrap()), 3);
    assert_eq!(
        result.checks.h_x,
        vec![vec![0, 1, 2, 3, 4, 5, 6, 7], vec![4, 5, 6, 7, 8, 9, 10, 11]]
    );
    assert_eq!(
        result.checks.h_z,
        vec![
            vec![0, 1],
            vec![1, 2],
            vec![2, 3],
            vec![4, 5],
            vec![5, 6],
            vec![6, 7],
            vec![8, 9],
            vec![9, 10],
            vec![10, 11],
        ]
    );
    assert_canonical_sparse_rows(&result.checks.h_x);
    assert_canonical_sparse_rows(&result.checks.h_z);
    verify_css_orthogonality(result.stats.n, &result.checks.h_x, &result.checks.h_z).unwrap();
    assert_eq!(
        compute_distance(css_code_from_result(&result).code())
            .unwrap()
            .distance,
        3
    );

    let dir = tempdir().unwrap();
    let spec_path = write_spec(
        dir.path(),
        "shor-like-3x4.json",
        r#"{"schema_version":1,"construction":"shor_like","outer_blocks":3,"inner_block":4}"#,
    );
    let cli_hz = cli_export_from_spec(spec_path, CssMatrixKind::Hz);
    assert_eq!(
        cli_hz,
        SparseRowsMatrix::new(result.stats.n, result.checks.h_z.clone())
            .unwrap()
            .to_json_string()
    );
}

#[test]
fn shor_like_rejects_invalid_dimensions() {
    for spec in [
        ShorLikeSpec {
            outer_blocks: 1,
            inner_block: 3,
        },
        ShorLikeSpec {
            outer_blocks: 3,
            inner_block: 1,
        },
        ShorLikeSpec {
            outer_blocks: 0,
            inner_block: 3,
        },
        ShorLikeSpec {
            outer_blocks: 3,
            inner_block: 0,
        },
    ] {
        assert!(matches!(
            construct_css(CssFamilySpec::ShorLike(spec).into()),
            Err(QecError::InvalidCssConstruction { construction, reason })
                if construction == "shor_like" && reason.contains("at least 2")
        ));
    }

    for body in [
        r#"{"schema_version":1,"construction":"shor_like","inner_block":3}"#,
        r#"{"schema_version":1,"construction":"shor_like","outer_blocks":3}"#,
        r#"{"schema_version":1,"construction":"shor_like","outer_blocks":0,"inner_block":3}"#,
        r#"{"schema_version":1,"construction":"shor_like","outer_blocks":3,"inner_block":0}"#,
    ] {
        assert!(matches!(
            parse_css_construction_json(body),
            Err(QecError::InvalidCssConstruction { construction, .. })
                if construction == "shor_like"
        ));
    }

    assert!(matches!(
        construct_css(CssFamilySpec::ShorLike(ShorLikeSpec {
            outer_blocks: usize::MAX,
            inner_block: 2,
        }).into()),
        Err(QecError::InvalidCssConstruction { construction, reason })
            if construction == "shor_like" && reason.contains("overflow")
    ));

    let json_overflow = format!(
        r#"{{"schema_version":1,"construction":"shor_like","outer_blocks":{},"inner_block":2}}"#,
        usize::MAX
    );
    let parsed = parse_css_construction_json(&json_overflow).unwrap();
    assert!(matches!(
        construct_css(parsed),
        Err(QecError::InvalidCssConstruction { construction, reason })
            if construction == "shor_like" && reason.contains("overflow")
    ));
}