microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
iadavis/openqasm-extern-compilation

Branches

Tags

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

Clone

HTTPS

Download ZIP

source/resource_estimator/src/system/data/logical_counts.rs

151lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::{
5 estimates::{ErrorBudget, ErrorBudgetStrategy, Overhead},
6 system::constants::{
7 NUM_MEASUREMENTS_PER_R, NUM_MEASUREMENTS_PER_TOF, NUM_TS_PER_ROTATION_A_COEFFICIENT,
8 NUM_TS_PER_ROTATION_B_COEFFICIENT,
9 },
10};
11use serde::{Deserialize, Serialize};
12
13use super::PartitioningOverhead;
14
15pub trait LayoutReportData {
16 fn num_qubits(&self) -> u64;
17 fn t_count(&self) -> u64;
18 fn rotation_count(&self) -> u64;
19 fn rotation_depth(&self) -> u64;
20 fn ccz_count(&self) -> u64;
21 fn ccix_count(&self) -> u64;
22 fn measurement_count(&self) -> u64;
23 fn num_ts_per_rotation(&self, eps_synthesis: f64) -> Option<u64>;
24}
25
26/// Resource counts output from `qir_estimate_counts` program
27#[derive(Default, Debug, Deserialize, Serialize)]
28#[serde(
29 rename_all(deserialize = "camelCase", serialize = "camelCase"),
30 deny_unknown_fields
31)]
32pub struct LogicalResourceCounts {
33 pub num_qubits: u64,
34 #[serde(default)]
35 pub t_count: u64,
36 #[serde(default)]
37 pub rotation_count: u64,
38 #[serde(default)]
39 pub rotation_depth: u64,
40 #[serde(default)]
41 pub ccz_count: u64,
42 #[serde(default)]
43 pub ccix_count: u64,
44 #[serde(default)]
45 pub measurement_count: u64,
46}
47
48/// Models the logical resources after layout
49///
50/// The logical resources comprise the logical depth, the number of qubits, and
51/// the number of T states. If there are rotations, optionally the number of T
52/// gates per rotation are specified.
53impl Overhead for LogicalResourceCounts {
54 // number of qubits per one logical qubit (part of Q in paper)
55 fn logical_qubits(&self) -> Result<u64, String> {
56 // number of logical qubits for padding (part of Q in paper)
57 let qubit_padding = ((8 * self.num_qubits) as f64).sqrt().ceil() as u64 + 1;
58
59 Ok(2 * self.num_qubits + qubit_padding)
60 }
61
62 fn logical_depth(&self, budget: &ErrorBudget) -> Result<u64, String> {
63 Ok(
64 (self.measurement_count + self.rotation_count + self.t_count) * NUM_MEASUREMENTS_PER_R
65 + (self.ccz_count + self.ccix_count) * NUM_MEASUREMENTS_PER_TOF
66 + self
67 .num_ts_per_rotation(budget.rotations())
68 .unwrap_or_default()
69 * self.rotation_depth
70 * NUM_MEASUREMENTS_PER_R,
71 )
72 }
73
74 fn num_magic_states(&self, budget: &ErrorBudget, _index: usize) -> Result<u64, String> {
75 Ok(4 * (self.ccz_count + self.ccix_count)
76 + self.t_count
77 + self
78 .num_ts_per_rotation(budget.rotations())
79 .unwrap_or_default()
80 * self.rotation_count)
81 }
82
83 fn prune_error_budget(&self, budget: &mut ErrorBudget, strategy: ErrorBudgetStrategy) {
84 if matches![strategy, ErrorBudgetStrategy::PruneLogicalAndRotations] {
85 if let Some(num_ts_per_rotation) = self.num_ts_per_rotation(budget.rotations()) {
86 let new_rotations_budget = (self.rotation_count as f64)
87 / 2.0_f64.powf(
88 ((num_ts_per_rotation as f64) - NUM_TS_PER_ROTATION_B_COEFFICIENT)
89 / NUM_TS_PER_ROTATION_A_COEFFICIENT,
90 );
91
92 let diff = budget.rotations() - new_rotations_budget;
93 budget.set_rotations(new_rotations_budget);
94 budget.set_magic_states(budget.magic_states() + diff);
95 }
96 }
97 }
98}
99
100impl PartitioningOverhead for LogicalResourceCounts {
101 fn has_tgates(&self) -> bool {
102 self.t_count > 0 || self.ccz_count > 0 || self.ccix_count > 0 || self.rotation_count > 0
103 }
104
105 fn has_rotations(&self) -> bool {
106 self.rotation_count > 0
107 }
108}
109
110impl LayoutReportData for LogicalResourceCounts {
111 fn num_qubits(&self) -> u64 {
112 self.num_qubits
113 }
114
115 fn t_count(&self) -> u64 {
116 self.t_count
117 }
118
119 fn rotation_count(&self) -> u64 {
120 self.rotation_count
121 }
122
123 fn rotation_depth(&self) -> u64 {
124 self.rotation_depth
125 }
126
127 fn ccz_count(&self) -> u64 {
128 self.ccz_count
129 }
130
131 fn ccix_count(&self) -> u64 {
132 self.ccix_count
133 }
134
135 fn measurement_count(&self) -> u64 {
136 self.measurement_count
137 }
138
139 fn num_ts_per_rotation(&self, eps_synthesis: f64) -> Option<u64> {
140 if self.rotation_count > 0 {
141 Some(
142 (NUM_TS_PER_ROTATION_A_COEFFICIENT
143 * ((self.rotation_count as f64) / eps_synthesis).log2()
144 + NUM_TS_PER_ROTATION_B_COEFFICIENT)
145 .ceil() as _,
146 )
147 } else {
148 None
149 }
150 }
151}
152