microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
billti/num2-sim

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/resource_estimator/src/system/optimization/distillation_units_map.rs

255lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#[cfg(test)]
5mod tests;
6
7use std::cmp::max;
8
9use std::rc::Rc;
10
11use crate::estimates::LogicalPatch;
12use crate::system::modeling::{
13 PhysicalQubit, Protocol, TFactoryDistillationUnit, TFactoryDistillationUnitTemplate,
14 TFactoryDistillationUnitType, TFactoryQubit,
15};
16
17pub struct DistillationUnitsMap<'a> {
18 physical_distillation_units: Vec<TFactoryDistillationUnit<'a>>,
19 is_valid_physical_distillation_units: Vec<bool>,
20 logical_distillation_units: Vec<Vec<TFactoryDistillationUnit<'a>>>,
21 num_combined_distillation_units: usize,
22 num_physical_distillation_units: usize,
23 num_logical_distillation_units: usize,
24 min_valid_code_distance_indexes: Vec<usize>,
25 num_code_distances: usize,
26 distances: Vec<u64>,
27}
28
29impl<'a> DistillationUnitsMap<'a> {
30 pub fn create(
31 qubit: &PhysicalQubit,
32 qubits: &[Option<Rc<LogicalPatch<Protocol>>>],
33 distances: Vec<u64>,
34 distillation_unit_templates: &'a [TFactoryDistillationUnitTemplate],
35 ) -> Self {
36 let num_code_distances = distances.len();
37 let combined_distillation_unit_templates = Self::get_templates_for_unit_type(
38 distillation_unit_templates,
39 TFactoryDistillationUnitType::Combined,
40 );
41 let num_combined_distillation_units = combined_distillation_unit_templates.len();
42
43 let mut purely_logical_distillation_unit_templates = Self::get_templates_for_unit_type(
44 distillation_unit_templates,
45 TFactoryDistillationUnitType::Logical,
46 );
47 let num_logical_distillation_units = purely_logical_distillation_unit_templates.len();
48
49 let mut physical_distillation_units: Vec<TFactoryDistillationUnit> =
50 combined_distillation_unit_templates
51 .iter()
52 .map(|x| TFactoryDistillationUnit::by_template(x, &TFactoryQubit::Physical(qubit)))
53 .collect();
54
55 let mut purely_physical_distillation_units: Vec<TFactoryDistillationUnit> =
56 distillation_unit_templates
57 .iter()
58 .filter(|x| x.unit_type == TFactoryDistillationUnitType::Physical)
59 .map(|x| TFactoryDistillationUnit::by_template(x, &TFactoryQubit::Physical(qubit)))
60 // exclude purely invalid physical distillation units from scratch
61 .filter(TFactoryDistillationUnit::is_valid)
62 .collect();
63
64 let num_physical_distillation_units = purely_physical_distillation_units.len();
65 physical_distillation_units.append(&mut purely_physical_distillation_units);
66
67 let mut is_valid_physical_distillation_units =
68 vec![true; num_combined_distillation_units + num_physical_distillation_units];
69
70 for idx in 0..num_combined_distillation_units {
71 if !physical_distillation_units[idx].is_valid() {
72 is_valid_physical_distillation_units[idx] = false;
73 }
74 }
75
76 let mut logical_distillation_unit_templates = combined_distillation_unit_templates;
77 logical_distillation_unit_templates.append(&mut purely_logical_distillation_unit_templates);
78
79 let mut logical_distillation_units: Vec<Vec<TFactoryDistillationUnit>> = Vec::new();
80
81 for qubit in qubits {
82 if let Some(qubit) = qubit {
83 logical_distillation_units.push(
84 logical_distillation_unit_templates
85 .iter()
86 .map(|x| {
87 TFactoryDistillationUnit::by_template(x, &TFactoryQubit::Logical(qubit))
88 })
89 .collect(),
90 );
91 } else {
92 logical_distillation_units.push(Vec::new());
93 }
94 }
95
96 let mut min_valid_code_distance_indexes =
97 vec![qubits.len(); num_logical_distillation_units + num_combined_distillation_units];
98 for idx in 0..num_logical_distillation_units + num_combined_distillation_units {
99 if let Some(min_valid_code_distance_index) = logical_distillation_units
100 .iter()
101 .filter(|x| !x.is_empty())
102 .enumerate()
103 .filter_map(|(distance_index, x)| {
104 if x[idx].is_valid() {
105 Some(distance_index)
106 } else {
107 None
108 }
109 })
110 .min()
111 {
112 min_valid_code_distance_indexes[idx] = min_valid_code_distance_index;
113 }
114 }
115
116 Self {
117 physical_distillation_units,
118 is_valid_physical_distillation_units,
119 logical_distillation_units,
120 num_combined_distillation_units,
121 num_physical_distillation_units,
122 num_logical_distillation_units,
123 min_valid_code_distance_indexes,
124 num_code_distances,
125 distances,
126 }
127 }
128
129 fn get_templates_for_unit_type(
130 distillation_unit_templates: &[TFactoryDistillationUnitTemplate],
131 unit_type: TFactoryDistillationUnitType,
132 ) -> Vec<&TFactoryDistillationUnitTemplate> {
133 distillation_unit_templates
134 .iter()
135 .filter(|x| x.unit_type == unit_type)
136 .collect()
137 }
138
139 fn get(&self, position: usize, distance: u64, idx: usize) -> &TFactoryDistillationUnit {
140 // physical: combined, purely physical
141 // logical: combined, purely logical
142 // enumeration: combined, purely logical, purely physical
143 if distance == 1 && position == 0 {
144 let index = if idx < self.num_combined_distillation_units {
145 idx
146 } else {
147 idx - self.num_logical_distillation_units
148 };
149
150 &self.physical_distillation_units[index]
151 } else {
152 &self.logical_distillation_units[distance as usize][idx]
153 }
154 }
155
156 pub fn get_min_distance_indexes(&self, indexes: &[usize]) -> Vec<usize> {
157 indexes
158 .iter()
159 .enumerate()
160 .scan(0, |state, (position, &idx)| {
161 *state = max(*state, self.get_min_distance_index(position, idx));
162 Some(*state)
163 })
164 .collect()
165 }
166
167 pub fn get_max_distance_indexes(&self, indexes: &[usize]) -> Vec<usize> {
168 indexes
169 .iter()
170 .enumerate()
171 .map(|(position, &idx)| self.get_max_distance_index(position, idx))
172 .collect()
173 }
174
175 fn get_min_distance_index(&self, position: usize, idx: usize) -> usize {
176 if position == 0 {
177 if idx >= self.num_logical_distillation_units + self.num_combined_distillation_units {
178 0
179 } else if idx < self.num_combined_distillation_units {
180 if self.is_valid_physical_distillation_units[idx] {
181 0
182 } else {
183 max(1, self.min_valid_code_distance_indexes[idx])
184 }
185 } else {
186 // skip code distance = 1 for logical units at first round of distillation
187 max(1, self.min_valid_code_distance_indexes[idx])
188 }
189 } else if idx >= self.num_logical_distillation_units + self.num_combined_distillation_units
190 {
191 panic!("Invalid position for physical unit: {position}")
192 } else {
193 self.min_valid_code_distance_indexes[idx]
194 }
195 }
196
197 fn get_max_distance_index(&self, position: usize, idx: usize) -> usize {
198 if idx >= self.num_logical_distillation_units + self.num_combined_distillation_units {
199 if position == 0 {
200 0
201 } else {
202 panic!("Invalid position for physical unit: {position}")
203 }
204 } else {
205 self.num_code_distances - 1
206 }
207 }
208
209 pub fn get_many(
210 &self,
211 distance_indexes: &[usize],
212 indexes: &[usize],
213 ) -> Vec<&TFactoryDistillationUnit> {
214 indexes
215 .iter()
216 .zip(distance_indexes)
217 .enumerate()
218 .map(|(position, (&idx, &distance_index))| {
219 self.get(position, self.distances[distance_index], idx)
220 })
221 .collect()
222 }
223
224 pub fn iterate_for_all_distillation_units<F>(&self, num_rounds: usize, action: &mut F)
225 where
226 F: FnMut(&[usize]),
227 {
228 let mut a: Vec<usize> = vec![0; num_rounds + 1];
229 loop {
230 action(&a[1..]);
231 let mut j = num_rounds;
232 while a[j]
233 == if j == 0 {
234 1
235 } else if j == 1 {
236 self.num_logical_distillation_units
237 + self.num_combined_distillation_units
238 + self.num_physical_distillation_units
239 - 1
240 } else {
241 self.num_logical_distillation_units + self.num_combined_distillation_units - 1
242 }
243 {
244 a[j] = 0;
245 j -= 1;
246 }
247
248 if j == 0 {
249 break;
250 }
251
252 a[j] += 1;
253 }
254 }
255}
256