Skip to main content

qec_code/codes/
random_hgp.rs

1use serde::Deserialize;
2
3use crate::error::{QecError, Result};
4use crate::family_contract::{CssClassicalCheckSpec, HypergraphProductSpec};
5use crate::regular_classical::{RegularClassicalMatrixConfig, deterministic_regular_matrix};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
8pub struct RegularClassicalCodeSpec {
9    pub column_count: usize,
10    pub row_count: usize,
11    pub column_weight: usize,
12    pub row_weight: usize,
13    pub seed: u64,
14    pub algorithm_version: u32,
15    pub retry_limit: usize,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct RandomHgpSpec {
20    pub left: RegularClassicalCodeSpec,
21    pub right: RegularClassicalCodeSpec,
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct RandomHgpClassicalSample {
26    pub spec: RegularClassicalCodeSpec,
27    pub rows: Vec<Vec<usize>>,
28}
29
30#[derive(Debug, Clone, PartialEq, Eq)]
31pub struct RandomHgpClassicalSamples {
32    pub left: RandomHgpClassicalSample,
33    pub right: RandomHgpClassicalSample,
34}
35
36#[derive(Debug, Deserialize)]
37struct RandomHgpSpecJson {
38    left: RegularClassicalCodeSpecJson,
39    right: RegularClassicalCodeSpecJson,
40}
41
42#[derive(Debug, Deserialize)]
43struct RegularClassicalCodeSpecJson {
44    column_count: usize,
45    row_count: usize,
46    column_weight: usize,
47    row_weight: usize,
48    seed: Option<u64>,
49    algorithm_version: u32,
50    retry_limit: usize,
51}
52
53impl RandomHgpSpec {
54    pub fn new(left: RegularClassicalCodeSpec, right: RegularClassicalCodeSpec) -> Result<Self> {
55        Ok(Self { left, right })
56    }
57}
58
59pub fn random_hgp_spec_from_json_str(input: &str) -> Result<RandomHgpSpec> {
60    let parsed: RandomHgpSpecJson = serde_json::from_str(input)
61        .map_err(|error| QecError::InvalidCssConstructionJson(error.to_string()))?;
62    RandomHgpSpec::new(
63        regular_spec_from_json(parsed.left)?,
64        regular_spec_from_json(parsed.right)?,
65    )
66}
67
68pub fn sample_random_hgp_classical_matrices(
69    spec: &RandomHgpSpec,
70) -> Result<RandomHgpClassicalSamples> {
71    Ok(RandomHgpClassicalSamples {
72        left: sample_classical(spec.left)?,
73        right: sample_classical(spec.right)?,
74    })
75}
76
77pub fn sampled_random_hgp_to_hgp_spec(
78    samples: &RandomHgpClassicalSamples,
79) -> HypergraphProductSpec {
80    HypergraphProductSpec {
81        left: CssClassicalCheckSpec {
82            num_cols: samples.left.spec.column_count,
83            rows: samples.left.rows.clone(),
84        },
85        right: CssClassicalCheckSpec {
86            num_cols: samples.right.spec.column_count,
87            rows: samples.right.rows.clone(),
88        },
89    }
90}
91
92fn regular_spec_from_json(
93    parsed: RegularClassicalCodeSpecJson,
94) -> Result<RegularClassicalCodeSpec> {
95    let seed = parsed.seed.ok_or_else(|| QecError::InvalidRandomHgpSpec {
96        option: "seed",
97        reason: "must be provided".to_owned(),
98    })?;
99    Ok(RegularClassicalCodeSpec {
100        column_count: parsed.column_count,
101        row_count: parsed.row_count,
102        column_weight: parsed.column_weight,
103        row_weight: parsed.row_weight,
104        seed,
105        algorithm_version: parsed.algorithm_version,
106        retry_limit: parsed.retry_limit,
107    })
108}
109
110fn sample_classical(spec: RegularClassicalCodeSpec) -> Result<RandomHgpClassicalSample> {
111    let rows = deterministic_regular_matrix(RegularClassicalMatrixConfig {
112        column_count: spec.column_count,
113        row_count: spec.row_count,
114        column_weight: spec.column_weight,
115        row_weight: spec.row_weight,
116        seed: spec.seed,
117        algorithm_version: spec.algorithm_version,
118        retry_limit: spec.retry_limit,
119    })?;
120    Ok(RandomHgpClassicalSample { spec, rows })
121}