qec_code/codes/
random_hgp.rs1use 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}