microsoft/qdk

Public

mirrored fromhttps://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.rs

147lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4// Calculations make frequent use of conversion back and forth between f64 and u64.
5#![allow(
6 clippy::cast_precision_loss,
7 clippy::cast_possible_truncation,
8 clippy::cast_sign_loss
9)]
10
11#[cfg(test)]
12mod tests;
13
14mod compiled_expression;
15mod constants;
16mod data;
17pub(crate) mod error;
18mod modeling;
19mod optimization;
20mod serialization;
21
22use crate::estimates::{Overhead, PhysicalResourceEstimation};
23use std::rc::Rc;
24
25pub use self::modeling::{
26 GateBasedPhysicalQubit, MajoranaQubit, PhysicalQubit, Protocol, ProtocolEvaluator,
27 ProtocolSpecification, TFactory, floquet_code, load_protocol_from_specification,
28 surface_code_gate_based, surface_code_measurement_based,
29};
30pub use self::optimization::TFactoryBuilder;
31pub use self::{data::LogicalResourceCounts, error::Error};
32use data::{EstimateType, JobParams};
33pub use data::{LayoutReportData, PartitioningOverhead};
34use serde::Serialize;
35
36pub(crate) type Result<T> = std::result::Result<T, error::Error>;
37
38pub fn estimate_physical_resources_from_json(
39 logical_resources: &str,
40 params: &str,
41) -> std::result::Result<String, Error> {
42 let logical_resources: LogicalResourceCounts = serde_json::from_str(logical_resources)
43 .map_err(|e| error::Error::IO(error::IO::CannotParseJSON(e)))?;
44 estimate_physical_resources(logical_resources, params)
45}
46
47pub fn estimate_physical_resources<
48 L: Overhead + LayoutReportData + PartitioningOverhead + Serialize,
49>(
50 logical_resources: L,
51 params: &str,
52) -> Result<String> {
53 let job_params_array = if params.is_empty() {
54 vec![JobParams::default()]
55 } else {
56 serde_json::from_str(params).map_err(|e| error::Error::IO(error::IO::CannotParseJSON(e)))?
57 };
58
59 let mut results: Vec<String> = Vec::with_capacity(job_params_array.len());
60 let logical_resources = Rc::new(logical_resources);
61 for job_params in job_params_array {
62 let result = estimate_single(logical_resources.clone(), job_params);
63 match result {
64 Ok(result) => results.push(
65 serde_json::to_string(&result).expect("serializing to json string should succeed"),
66 ),
67 Err(err) => {
68 results.push(serialize_error(err));
69 }
70 }
71 }
72
73 Ok(format!("[{}]", results.join(",")))
74}
75
76fn estimate_single<L: Overhead + LayoutReportData + PartitioningOverhead + Serialize>(
77 logical_resources: Rc<L>,
78 mut job_params: JobParams,
79) -> Result<data::Success<L>> {
80 let qubit = job_params.qubit_params().clone();
81
82 let ftp = load_protocol_from_specification(job_params.qec_scheme_mut(), &qubit)?;
83 let distillation_unit_templates = job_params
84 .distillation_unit_specifications()
85 .as_templates()?;
86 // create error budget partitioning
87 let partitioning = job_params
88 .error_budget()
89 .partitioning(logical_resources.as_ref())?;
90
91 // The clone on the logical resources is on an Rc and therefore inexpensive,
92 // the value is later used in creating the result object
93 let mut estimation = PhysicalResourceEstimation::new(
94 ftp,
95 qubit,
96 TFactoryBuilder::new(
97 distillation_unit_templates,
98 job_params.constraints().max_distillation_rounds,
99 ),
100 logical_resources.clone(),
101 );
102 if let Some(logical_depth_factor) = job_params.constraints().logical_depth_factor {
103 estimation.set_logical_depth_factor(logical_depth_factor);
104 }
105 if let Some(max_t_factories) = job_params.constraints().max_t_factories {
106 estimation.set_max_factories(max_t_factories);
107 }
108 if let Some(max_duration) = job_params.constraints().max_duration {
109 estimation.set_max_duration(max_duration);
110 }
111 if let Some(max_physical_qubits) = job_params.constraints().max_physical_qubits {
112 estimation.set_max_physical_qubits(max_physical_qubits);
113 }
114
115 match job_params.estimate_type() {
116 EstimateType::Frontier => {
117 if job_params.constraints().max_duration.is_some()
118 || job_params.constraints().max_physical_qubits.is_some()
119 || job_params.constraints().max_t_factories.is_some()
120 {
121 // We can technically handle those scenarios but do not see a practial use case for it.
122 return Err(error::Error::InvalidInput(
123 error::InvalidInput::ConstraintsProvidedForFrontierEstimation,
124 ));
125 }
126
127 let estimation_result = estimation
128 .build_frontier(&partitioning)
129 .map_err(std::convert::Into::into);
130 estimation_result.map(|result| {
131 data::Success::new_from_multiple(job_params, logical_resources, result)
132 })
133 }
134 EstimateType::SinglePoint => {
135 let estimation_result = estimation
136 .estimate(&partitioning)
137 .map_err(std::convert::Into::into);
138 estimation_result
139 .map(|result| data::Success::new(job_params, logical_resources, result))
140 }
141 }
142}
143
144fn serialize_error(err: error::Error) -> String {
145 serde_json::to_string(&data::Failure::new(err))
146 .expect("serializing to json string should succeed")
147}
148