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/estimates/physical_estimation/result.rs

225lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use serde::Serialize;
5
6use crate::estimates::{
7 Error, ErrorBudget, ErrorCorrection, Factory, FactoryBuilder, LogicalPatch, Overhead,
8 PhysicalResourceEstimation, RealizedOverhead,
9};
10
11/// Resource estimation result
12#[derive(Serialize)]
13#[serde(rename_all = "camelCase")]
14pub struct PhysicalResourceEstimationResult<E: ErrorCorrection, F> {
15 #[serde(bound = "E::Parameter: Serialize")]
16 logical_patch: LogicalPatch<E>,
17 num_cycles: u64,
18 #[serde(bound = "F: Serialize")]
19 factory_parts: Vec<Option<FactoryPart<F>>>,
20 required_logical_error_rate: f64,
21 physical_qubits_for_factories: u64,
22 physical_qubits_for_algorithm: u64,
23 physical_qubits: u64,
24 runtime: u64,
25 rqops: u64,
26 layout_overhead: RealizedOverhead,
27 error_budget: ErrorBudget,
28}
29
30impl<E: ErrorCorrection<Parameter = impl Clone>, F: Factory<Parameter = E::Parameter> + Clone>
31 PhysicalResourceEstimationResult<E, F>
32{
33 pub fn new(
34 estimation: &PhysicalResourceEstimation<
35 E,
36 impl FactoryBuilder<E, Factory = F>,
37 impl Overhead,
38 >,
39 logical_patch: LogicalPatch<E>,
40 error_budget: &ErrorBudget,
41 num_cycles: u64,
42 factory_parts: Vec<Option<FactoryPart<F>>>,
43 required_logical_error_rate: f64,
44 ) -> Result<Self, Error> {
45 let physical_qubits_for_factories = factory_parts
46 .iter()
47 .filter_map(|f| f.as_ref().map(FactoryPart::physical_qubits))
48 .sum();
49 let num_logical_qubits = estimation
50 .layout_overhead
51 .logical_qubits()
52 .map_err(Error::AlgorithmicLogicalQubitsComputationFailed)?;
53 let num_logical_patches = num_logical_qubits.div_ceil(logical_patch.logical_qubits());
54 let physical_qubits_for_algorithm = num_logical_patches * logical_patch.physical_qubits();
55
56 let physical_qubits = physical_qubits_for_algorithm + physical_qubits_for_factories;
57
58 let runtime = (logical_patch.logical_cycle_time()) * num_cycles;
59
60 let rqops =
61 (num_logical_qubits as f64 * logical_patch.logical_cycles_per_second()).ceil() as u64;
62
63 Ok(Self {
64 logical_patch,
65 num_cycles,
66 factory_parts,
67 required_logical_error_rate,
68 physical_qubits_for_factories,
69 physical_qubits_for_algorithm,
70 physical_qubits,
71 runtime,
72 rqops,
73 layout_overhead: RealizedOverhead::from_overhead(
74 estimation.layout_overhead(),
75 error_budget,
76 estimation.factory_builder().num_magic_state_types(),
77 )?,
78 error_budget: error_budget.clone(),
79 })
80 }
81
82 pub fn without_factories(
83 estimation: &PhysicalResourceEstimation<
84 E,
85 impl FactoryBuilder<E, Factory = F>,
86 impl Overhead,
87 >,
88 logical_patch: LogicalPatch<E>,
89 error_budget: &ErrorBudget,
90 num_cycles: u64,
91 required_logical_patch_error_rate: f64,
92 ) -> Result<Self, Error> {
93 Self::new(
94 estimation,
95 logical_patch,
96 error_budget,
97 num_cycles,
98 std::iter::repeat(())
99 .map(|()| None)
100 .take(estimation.factory_builder.num_magic_state_types())
101 .collect(),
102 required_logical_patch_error_rate,
103 )
104 }
105
106 pub fn logical_patch(&self) -> &LogicalPatch<E> {
107 &self.logical_patch
108 }
109
110 pub fn take(self) -> (LogicalPatch<E>, Vec<Option<FactoryPart<F>>>, ErrorBudget) {
111 (self.logical_patch, self.factory_parts, self.error_budget)
112 }
113
114 pub fn num_cycles(&self) -> u64 {
115 self.num_cycles
116 }
117
118 pub fn factory_parts(&self) -> &[Option<FactoryPart<F>>] {
119 &self.factory_parts
120 }
121
122 /// The required logical error rate for one logical operation on one logical
123 /// qubit
124 pub fn required_logical_error_rate(&self) -> f64 {
125 self.required_logical_error_rate
126 }
127
128 pub fn physical_qubits_for_factories(&self) -> u64 {
129 self.physical_qubits_for_factories
130 }
131
132 pub fn physical_qubits_for_algorithm(&self) -> u64 {
133 self.physical_qubits_for_algorithm
134 }
135
136 pub fn physical_qubits(&self) -> u64 {
137 self.physical_qubits
138 }
139
140 pub fn runtime(&self) -> u64 {
141 self.runtime
142 }
143
144 pub fn rqops(&self) -> u64 {
145 self.rqops
146 }
147
148 pub fn layout_overhead(&self) -> &RealizedOverhead {
149 &self.layout_overhead
150 }
151
152 pub fn error_budget(&self) -> &ErrorBudget {
153 &self.error_budget
154 }
155
156 pub fn algorithmic_logical_depth(&self) -> u64 {
157 self.layout_overhead.logical_depth()
158 }
159
160 /// The argument index indicates for which type of magic state (starting
161 /// from 0) the number is requested for.
162 pub fn num_magic_states(&self, index: usize) -> u64 {
163 self.layout_overhead.num_magic_states()[index]
164 }
165}
166
167/// Results for a factory part in the overall quantum algorithm
168#[derive(Serialize)]
169#[serde(rename_all = "camelCase", bound = "F: Serialize")]
170pub struct FactoryPart<F> {
171 /// The factory used in this part
172 factory: F,
173
174 /// The number of factory copies
175 copies: u64,
176
177 /// The number of factory runs
178 runs: u64,
179
180 /// The required logical magic state error rate used to find this factory
181 required_output_error_rate: f64,
182}
183
184impl<F: Factory> FactoryPart<F> {
185 pub fn new(
186 factory: F,
187 copies: u64,
188 num_magic_states: u64,
189 required_output_error_rate: f64,
190 ) -> Self {
191 let magic_states_per_run = copies * factory.num_output_states();
192 let runs = num_magic_states.div_ceil(magic_states_per_run);
193
194 Self {
195 factory,
196 copies,
197 runs,
198 required_output_error_rate,
199 }
200 }
201
202 pub fn factory(&self) -> &F {
203 &self.factory
204 }
205
206 pub fn copies(&self) -> u64 {
207 self.copies
208 }
209
210 pub fn runs(&self) -> u64 {
211 self.runs
212 }
213
214 pub fn required_output_error_rate(&self) -> f64 {
215 self.required_output_error_rate
216 }
217
218 pub fn physical_qubits(&self) -> u64 {
219 self.factory.physical_qubits() * self.copies
220 }
221
222 pub fn into_factory(self) -> F {
223 self.factory
224 }
225}
226