Diferentes maneras de ejecutar el estimador de recursos
En este artículo, aprenderá a trabajar con el estimador de recursos de Azure Quantum. El estimador de recursos está disponible tanto en VS Code como en línea en Azure Portal.
En la tabla siguiente se muestran las distintas formas de ejecutar el estimador de recursos.
Escenario de usuario | Plataforma | Tutorial |
---|---|---|
Estimación de los recursos de un programa de Q# | Visual Studio Code | Seleccione Q# en VS Code en la parte superior de la página. |
Estimación de los recursos de un programa de Q# (avanzado) | Jupyter Notebook en Visual Studio Code | Seleccione Q# en Jupyter Notebook en la parte superior de la página. |
Estimación de los recursos de un programa Qiskit | Portal de Azure Quantum | Seleccione Qiskit en Azure Portal en la parte superior de la página. |
Estimación de los recursos de un programa QIR | Portal de Azure Quantum | Enviar QIR |
Usar archivos FCIDUMP como parámetros de argumento (avanzado) | Visual Studio Code | Envío de un problema de química cuántica |
Nota
El Kit de desarrollo de Microsoft Quantum (QDK clásico) ya no se admitirá después del 30 de junio de 2024. Si es un desarrollador de QDK existente, se recomienda realizar la transición al nuevo kit de desarrollo de Azure Quantum (QDK moderno) para seguir desarrollando soluciones cuánticas. Para obtener más información, consulte Migración del código de Q# al QDK moderno.
Requisitos previos para VS Code
- La versión más reciente de Visual Studio Code o abra VS Code en la Web.
- La versión más reciente de la extensión del Kit de desarrollo de Azure Quantum . Para obtener más información sobre la instalación, consulte Instalación del QDK moderno en VS Code.
Sugerencia
No es necesario tener una cuenta de Azure para ejecutar el estimador de recursos local.
Create un nuevo archivo Q#
- Abra Visual Studio Code y seleccione Archivo > nuevo archivo de texto para crear un nuevo archivo.
- Guarde el archivo como
ShorRE.qs
. Este archivo contendrá el código Q# del programa.
Create el algoritmo cuántico
Copie el código siguiente en el archivo ShorRE.qs
:
namespace Shors {
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Measurement;
open Microsoft.Quantum.Unstable.Arithmetic;
open Microsoft.Quantum.ResourceEstimation;
@EntryPoint()
operation RunProgram() : Unit {
let bitsize = 31;
// When chooseing parameters for `EstimateFrequency`, make sure that
// generator and modules are not co-prime
let _ = EstimateFrequency(11, 2^bitsize - 1, bitsize);
}
// In this sample we concentrate on costing the `EstimateFrequency`
// operation, which is the core quantum operation in Shors algorithm, and
// we omit the classical pre- and post-processing.
/// # Summary
/// Estimates the frequency of a generator
/// in the residue ring Z mod `modulus`.
///
/// # Input
/// ## generator
/// The unsigned integer multiplicative order (period)
/// of which is being estimated. Must be co-prime to `modulus`.
/// ## modulus
/// The modulus which defines the residue ring Z mod `modulus`
/// in which the multiplicative order of `generator` is being estimated.
/// ## bitsize
/// Number of bits needed to represent the modulus.
///
/// # Output
/// The numerator k of dyadic fraction k/2^bitsPrecision
/// approximating s/r.
operation EstimateFrequency(
generator : Int,
modulus : Int,
bitsize : Int
)
: Int {
mutable frequencyEstimate = 0;
let bitsPrecision = 2 * bitsize + 1;
// Allocate qubits for the superposition of eigenstates of
// the oracle that is used in period finding.
use eigenstateRegister = Qubit[bitsize];
// Initialize eigenstateRegister to 1, which is a superposition of
// the eigenstates we are estimating the phases of.
// We first interpret the register as encoding an unsigned integer
// in little endian encoding.
ApplyXorInPlace(1, eigenstateRegister);
let oracle = ApplyOrderFindingOracle(generator, modulus, _, _);
// Use phase estimation with a semiclassical Fourier transform to
// estimate the frequency.
use c = Qubit();
for idx in bitsPrecision - 1..-1..0 {
within {
H(c);
} apply {
// `BeginEstimateCaching` and `EndEstimateCaching` are the operations
// exposed by Azure Quantum Resource Estimator. These will instruct
// resource counting such that the if-block will be executed
// only once, its resources will be cached, and appended in
// every other iteration.
if BeginEstimateCaching("ControlledOracle", SingleVariant()) {
Controlled oracle([c], (1 <<< idx, eigenstateRegister));
EndEstimateCaching();
}
R1Frac(frequencyEstimate, bitsPrecision - 1 - idx, c);
}
if MResetZ(c) == One {
set frequencyEstimate += 1 <<< (bitsPrecision - 1 - idx);
}
}
// Return all the qubits used for oracles eigenstate back to 0 state
// using Microsoft.Quantum.Intrinsic.ResetAll.
ResetAll(eigenstateRegister);
return frequencyEstimate;
}
/// # Summary
/// Interprets `target` as encoding unsigned little-endian integer k
/// and performs transformation |k⟩ ↦ |gᵖ⋅k mod N ⟩ where
/// p is `power`, g is `generator` and N is `modulus`.
///
/// # Input
/// ## generator
/// The unsigned integer multiplicative order ( period )
/// of which is being estimated. Must be co-prime to `modulus`.
/// ## modulus
/// The modulus which defines the residue ring Z mod `modulus`
/// in which the multiplicative order of `generator` is being estimated.
/// ## power
/// Power of `generator` by which `target` is multiplied.
/// ## target
/// Register interpreted as little endian encoded which is multiplied by
/// given power of the generator. The multiplication is performed modulo
/// `modulus`.
internal operation ApplyOrderFindingOracle(
generator : Int, modulus : Int, power : Int, target : Qubit[]
)
: Unit
is Adj + Ctl {
// The oracle we use for order finding implements |x⟩ ↦ |x⋅a mod N⟩. We
// also use `ExpModI` to compute a by which x must be multiplied. Also
// note that we interpret target as unsigned integer in little-endian
// encoding.
ModularMultiplyByConstant(modulus,
ExpModI(generator, power, modulus),
target);
}
/// # Summary
/// Performs modular in-place multiplication by a classical constant.
///
/// # Description
/// Given the classical constants `c` and `modulus`, and an input
/// quantum register |𝑦⟩, this operation
/// computes `(c*x) % modulus` into |𝑦⟩.
///
/// # Input
/// ## modulus
/// Modulus to use for modular multiplication
/// ## c
/// Constant by which to multiply |𝑦⟩
/// ## y
/// Quantum register of target
internal operation ModularMultiplyByConstant(modulus : Int, c : Int, y : Qubit[])
: Unit is Adj + Ctl {
use qs = Qubit[Length(y)];
for (idx, yq) in Enumerated(y) {
let shiftedC = (c <<< idx) % modulus;
Controlled ModularAddConstant([yq], (modulus, shiftedC, qs));
}
ApplyToEachCA(SWAP, Zipped(y, qs));
let invC = InverseModI(c, modulus);
for (idx, yq) in Enumerated(y) {
let shiftedC = (invC <<< idx) % modulus;
Controlled ModularAddConstant([yq], (modulus, modulus - shiftedC, qs));
}
}
/// # Summary
/// Performs modular in-place addition of a classical constant into a
/// quantum register.
///
/// # Description
/// Given the classical constants `c` and `modulus`, and an input
/// quantum register |𝑦⟩, this operation
/// computes `(x+c) % modulus` into |𝑦⟩.
///
/// # Input
/// ## modulus
/// Modulus to use for modular addition
/// ## c
/// Constant to add to |𝑦⟩
/// ## y
/// Quantum register of target
internal operation ModularAddConstant(modulus : Int, c : Int, y : Qubit[])
: Unit is Adj + Ctl {
body (...) {
Controlled ModularAddConstant([], (modulus, c, y));
}
controlled (ctrls, ...) {
// We apply a custom strategy to control this operation instead of
// letting the compiler create the controlled variant for us in which
// the `Controlled` functor would be distributed over each operation
// in the body.
//
// Here we can use some scratch memory to save ensure that at most one
// control qubit is used for costly operations such as `AddConstant`
// and `CompareGreaterThenOrEqualConstant`.
if Length(ctrls) >= 2 {
use control = Qubit();
within {
Controlled X(ctrls, control);
} apply {
Controlled ModularAddConstant([control], (modulus, c, y));
}
} else {
use carry = Qubit();
Controlled AddConstant(ctrls, (c, y + [carry]));
Controlled Adjoint AddConstant(ctrls, (modulus, y + [carry]));
Controlled AddConstant([carry], (modulus, y));
Controlled CompareGreaterThanOrEqualConstant(ctrls, (c, y, carry));
}
}
}
/// # Summary
/// Performs in-place addition of a constant into a quantum register.
///
/// # Description
/// Given a non-empty quantum register |𝑦⟩ of length 𝑛+1 and a positive
/// constant 𝑐 < 2ⁿ, computes |𝑦 + c⟩ into |𝑦⟩.
///
/// # Input
/// ## c
/// Constant number to add to |𝑦⟩.
/// ## y
/// Quantum register of second summand and target; must not be empty.
internal operation AddConstant(c : Int, y : Qubit[]) : Unit is Adj + Ctl {
// We are using this version instead of the library version that is based
// on Fourier angles to show an advantage of sparse simulation in this sample.
let n = Length(y);
Fact(n > 0, "Bit width must be at least 1");
Fact(c >= 0, "constant must not be negative");
Fact(c < 2 ^ n, $"constant must be smaller than {2L ^ n}");
if c != 0 {
// If c has j trailing zeroes than the j least significant bits
// of y won't be affected by the addition and can therefore be
// ignored by applying the addition only to the other qubits and
// shifting c accordingly.
let j = NTrailingZeroes(c);
use x = Qubit[n - j];
within {
ApplyXorInPlace(c >>> j, x);
} apply {
IncByLE(x, y[j...]);
}
}
}
/// # Summary
/// Performs greater-than-or-equals comparison to a constant.
///
/// # Description
/// Toggles output qubit `target` if and only if input register `x`
/// is greater than or equal to `c`.
///
/// # Input
/// ## c
/// Constant value for comparison.
/// ## x
/// Quantum register to compare against.
/// ## target
/// Target qubit for comparison result.
///
/// # Reference
/// This construction is described in [Lemma 3, arXiv:2201.10200]
internal operation CompareGreaterThanOrEqualConstant(c : Int, x : Qubit[], target : Qubit)
: Unit is Adj+Ctl {
let bitWidth = Length(x);
if c == 0 {
X(target);
} elif c >= 2 ^ bitWidth {
// do nothing
} elif c == 2 ^ (bitWidth - 1) {
ApplyLowTCNOT(Tail(x), target);
} else {
// normalize constant
let l = NTrailingZeroes(c);
let cNormalized = c >>> l;
let xNormalized = x[l...];
let bitWidthNormalized = Length(xNormalized);
let gates = Rest(IntAsBoolArray(cNormalized, bitWidthNormalized));
use qs = Qubit[bitWidthNormalized - 1];
let cs1 = [Head(xNormalized)] + Most(qs);
let cs2 = Rest(xNormalized);
within {
for i in IndexRange(gates) {
(gates[i] ? ApplyAnd | ApplyOr)(cs1[i], cs2[i], qs[i]);
}
} apply {
ApplyLowTCNOT(Tail(qs), target);
}
}
}
/// # Summary
/// Internal operation used in the implementation of GreaterThanOrEqualConstant.
internal operation ApplyOr(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj {
within {
ApplyToEachA(X, [control1, control2]);
} apply {
ApplyAnd(control1, control2, target);
X(target);
}
}
internal operation ApplyAnd(control1 : Qubit, control2 : Qubit, target : Qubit)
: Unit is Adj {
body (...) {
CCNOT(control1, control2, target);
}
adjoint (...) {
H(target);
if (M(target) == One) {
X(target);
CZ(control1, control2);
}
}
}
/// # Summary
/// Returns the number of trailing zeroes of a number
///
/// ## Example
/// ```qsharp
/// let zeroes = NTrailingZeroes(21); // = NTrailingZeroes(0b1101) = 0
/// let zeroes = NTrailingZeroes(20); // = NTrailingZeroes(0b1100) = 2
/// ```
internal function NTrailingZeroes(number : Int) : Int {
mutable nZeroes = 0;
mutable copy = number;
while (copy % 2 == 0) {
set nZeroes += 1;
set copy /= 2;
}
return nZeroes;
}
/// # Summary
/// An implementation for `CNOT` that when controlled using a single control uses
/// a helper qubit and uses `ApplyAnd` to reduce the T-count to 4 instead of 7.
internal operation ApplyLowTCNOT(a : Qubit, b : Qubit) : Unit is Adj+Ctl {
body (...) {
CNOT(a, b);
}
adjoint self;
controlled (ctls, ...) {
// In this application this operation is used in a way that
// it is controlled by at most one qubit.
Fact(Length(ctls) <= 1, "At most one control line allowed");
if IsEmpty(ctls) {
CNOT(a, b);
} else {
use q = Qubit();
within {
ApplyAnd(Head(ctls), a, q);
} apply {
CNOT(q, b);
}
}
}
controlled adjoint self;
}
}
Ejecución del estimador de recursos
El estimador de recursos ofrece seis parámetros de cúbit predefinidos, cuatro de los cuales tienen conjuntos de instrucciones basados en puertas y dos que tienen un conjunto de instrucciones Majorana. También ofrece dos códigos de corrección de errores cuánticos y surface_code
floquet_code
.
En este ejemplo, ejecutará el estimador de recursos mediante el qubit_gate_us_e3
parámetro qubit y el surface_code
código de corrección de errores cuánticos.
Seleccione Ver-> Paleta de comandos y escriba "recurso" que debería mostrar la opción Q#: Calculate Resource Estimates (Calcular estimaciones de recursos ). También puede hacer clic en Estimación en la lista de comandos siguientes
@EntryPoint()
. Seleccione esta opción para abrir la ventana Estimador de recursos.Puede seleccionar uno o varios parámetros qubit + tipos de código de corrección de errores para calcular los recursos de . En este ejemplo, seleccione qubit_gate_us_e3 y haga clic en Aceptar.
Especifique el presupuesto de errores o acepte el valor predeterminado 0.001. En este ejemplo, deje el valor predeterminado y presione Entrar.
Presione Entrar para aceptar el nombre de resultado predeterminado en función del nombre de archivo, en este caso, ShorRE.
Visualización de los resultados
El estimador de recursos proporciona varias estimaciones para el mismo algoritmo, cada una de las cuales muestra inconvenientes entre el número de cúbits y el tiempo de ejecución. Comprender el equilibrio entre el entorno de ejecución y la escala del sistema es uno de los aspectos más importantes de la estimación de recursos.
El resultado de la estimación de recursos se muestra en la ventana Estimación de Q# .
La pestaña Resultados muestra un resumen de la estimación de recursos. Haga clic en el icono situado junto a la primera fila para seleccionar las columnas que desea mostrar. Puede seleccionar entre el nombre de ejecución, el tipo de estimación, el tipo de cúbit, el esquema qec, el presupuesto de errores, los cúbits lógicos, la profundidad lógica, la distancia del código, los estados T, las factorías de T, la fracción de fábrica de T, el tiempo de ejecución, rQOPS y los cúbits físicos.
En la columna Tipo estimado de la tabla de resultados, puede ver el número de combinaciones óptimas de {número de cúbits, runtime} para el algoritmo. Estas combinaciones se pueden ver en el diagrama de tiempo espacial.
El diagrama de tiempo espaciado muestra los inconvenientes entre el número de cúbits físicos y el tiempo de ejecución del algoritmo. En este caso, el estimador de recursos encuentra 13 combinaciones óptimas diferentes de muchas miles posibles. Puede mantener el puntero sobre cada {número de cúbits, tiempo de ejecución} para ver los detalles de la estimación de recursos en ese momento.
Para obtener más información, vea Diagrama de tiempo espaciador.
Nota
Debe hacer clic en un punto del diagrama de tiempo espaciado, es decir, un par {número de cúbits, tiempo de ejecución}, para ver el diagrama de espacio y los detalles de la estimación de recursos correspondiente a ese punto.
En el diagrama space se muestra la distribución de cúbits físicos usados para el algoritmo y las factorías de T, correspondientes a un par {número de cúbits, runtime}. Por ejemplo, si selecciona el punto más a la izquierda en el diagrama de tiempo espacial, el número de cúbits físicos necesarios para ejecutar el algoritmo se 427726, 196686 de los cuales son cúbits de algoritmo y 231040 de los cuales son cúbits de fábrica de T.
Por último, la pestaña Estimaciones de recursos muestra la lista completa de datos de salida del estimador de recursos correspondiente a un par {número de cúbits, runtime} . Se pueden inspeccionar los detalles de los costos contrayendo los grupos, que contienen más información. Por ejemplo, seleccione el punto situado más a la izquierda en el diagrama de tiempo espaciado y contraiga el grupo Parámetros cuánticos lógicos .
Parámetro de cúbit lógico Valor Esquema de QEC surface_code Distancia del código 21 Cúbits físicos 882 Tiempo de ciclo lógico 13 milisecs Frecuencia de error de cúbit lógico 3.00E-13 Cruce del prefactor 0,03 Umbral de corrección de errores 0,01 Fórmula de tiempo de ciclo lógico (4 * twoQubitGateTime
+ 2 *oneQubitMeasurementTime
) *codeDistance
Fórmula de cúbits físicos 2 * codeDistance
*codeDistance
Sugerencia
Haga clic en Mostrar filas detalladas para mostrar la descripción de cada salida de los datos del informe.
Para obtener más información, consulte los datos completos del informe del estimador de recursos.
Cambio de los target parámetros
Puede calcular el costo del mismo programa de Q# con otro tipo de cúbit, código de corrección de errores y presupuesto de errores. Abra la ventana Estimador de recursos seleccionando Ver -> Paleta de comandos y escriba Q#: Calculate Resource Estimates
.
Seleccione cualquier otra configuración, por ejemplo, el parámetro de cúbit basado en Majorana, qubit_maj_ns_e6
. Acepte el valor predeterminado del presupuesto de errores o escriba uno nuevo y presione Entrar. El estimador de recursos vuelve a ejecutar la estimación con los nuevos target parámetros.
Para obtener más información, consulte Parámetros de destino para el estimador de recursos.
Ejecución de varias configuraciones de parámetros
El estimador de recursos de Azure Quantum puede ejecutar varias configuraciones de parámetros y comparar los resultados de target la estimación de recursos.
Seleccione Ver -> Paleta de comandos o presione Ctrl+Mayús+P y escriba
Q#: Calculate Resource Estimates
.Seleccione qubit_gate_us_e3, qubit_gate_us_e4, qubit_maj_ns_e4 + floquet_code y qubit_maj_ns_e6 + floquet_code y haga clic en Aceptar.
Acepte el valor predeterminado del presupuesto de errores 0.001 y presione Entrar.
Presione Entrar para aceptar el archivo de entrada, en este caso, ShorRE.qs.
En el caso de varias configuraciones de parámetros, los resultados se muestran en filas diferentes en la pestaña Resultados .
En el diagrama space-time se muestran los resultados de todas las configuraciones de parámetros. La primera columna de la tabla de resultados muestra la leyenda de cada configuración de parámetros. Puede mantener el puntero sobre cada punto para ver los detalles de la estimación de recursos en ese momento.
Haga clic en un {número de cúbits, tiempo de ejecución} del diagrama de tiempo de espacio para mostrar el diagrama de espacio y los datos del informe correspondientes.
Requisitos previos para Jupyter Notebook en VS Code
Un entorno de Python con Python y Pip instalado.
La versión más reciente de Visual Studio Code o abra VS Code en la Web.
VS Code con las extensiones de Azure Quantum Development Kit, Python y Jupyter instaladas.
Los paquetes y
qsharp-widgets
Azure Quantumqsharp
más recientes.python -m pip install --upgrade qsharp qsharp-widgets
Sugerencia
No es necesario tener una cuenta de Azure para ejecutar el estimador de recursos local.
Create el algoritmo cuántico
En VS Code, seleccione Ver > paleta de comandos y seleccione Create: Nuevo Jupyter Notebook.
En la parte superior derecha, VS Code detectará y mostrará la versión de Python y el entorno de Python virtual que se seleccionó para el cuaderno. Si tiene varios entornos de Python, es posible que tenga que seleccionar un kernel mediante el selector de kernel en la parte superior derecha. Si no se detectó ningún entorno, consulte Jupyter Notebooks in VS Code (Cuadernos de Jupyter Notebook en VS Code ) para obtener información de configuración.
En la primera celda del cuaderno, importe el
qsharp
paquete.import qsharp
Agregue una nueva celda y copie el código siguiente.
%%qsharp open Microsoft.Quantum.Arrays; open Microsoft.Quantum.Canon; open Microsoft.Quantum.Convert; open Microsoft.Quantum.Diagnostics; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Math; open Microsoft.Quantum.Measurement; open Microsoft.Quantum.Unstable.Arithmetic; open Microsoft.Quantum.ResourceEstimation; operation RunProgram() : Unit { let bitsize = 31; // When choosing parameters for `EstimateFrequency`, make sure that // generator and modules are not co-prime let _ = EstimateFrequency(11, 2^bitsize - 1, bitsize); } // In this sample we concentrate on costing the `EstimateFrequency` // operation, which is the core quantum operation in Shors algorithm, and // we omit the classical pre- and post-processing. /// # Summary /// Estimates the frequency of a generator /// in the residue ring Z mod `modulus`. /// /// # Input /// ## generator /// The unsigned integer multiplicative order (period) /// of which is being estimated. Must be co-prime to `modulus`. /// ## modulus /// The modulus which defines the residue ring Z mod `modulus` /// in which the multiplicative order of `generator` is being estimated. /// ## bitsize /// Number of bits needed to represent the modulus. /// /// # Output /// The numerator k of dyadic fraction k/2^bitsPrecision /// approximating s/r. operation EstimateFrequency( generator : Int, modulus : Int, bitsize : Int ) : Int { mutable frequencyEstimate = 0; let bitsPrecision = 2 * bitsize + 1; // Allocate qubits for the superposition of eigenstates of // the oracle that is used in period finding. use eigenstateRegister = Qubit[bitsize]; // Initialize eigenstateRegister to 1, which is a superposition of // the eigenstates we are estimating the phases of. // We first interpret the register as encoding an unsigned integer // in little endian encoding. ApplyXorInPlace(1, eigenstateRegister); let oracle = ApplyOrderFindingOracle(generator, modulus, _, _); // Use phase estimation with a semiclassical Fourier transform to // estimate the frequency. use c = Qubit(); for idx in bitsPrecision - 1..-1..0 { within { H(c); } apply { // `BeginEstimateCaching` and `EndEstimateCaching` are the operations // exposed by Azure Quantum Resource Estimator. These will instruct // resource counting such that the if-block will be executed // only once, its resources will be cached, and appended in // every other iteration. if BeginEstimateCaching("ControlledOracle", SingleVariant()) { Controlled oracle([c], (1 <<< idx, eigenstateRegister)); EndEstimateCaching(); } R1Frac(frequencyEstimate, bitsPrecision - 1 - idx, c); } if MResetZ(c) == One { set frequencyEstimate += 1 <<< (bitsPrecision - 1 - idx); } } // Return all the qubits used for oracle eigenstate back to 0 state // using Microsoft.Quantum.Intrinsic.ResetAll. ResetAll(eigenstateRegister); return frequencyEstimate; } /// # Summary /// Interprets `target` as encoding unsigned little-endian integer k /// and performs transformation |k⟩ ↦ |gᵖ⋅k mod N ⟩ where /// p is `power`, g is `generator` and N is `modulus`. /// /// # Input /// ## generator /// The unsigned integer multiplicative order ( period ) /// of which is being estimated. Must be co-prime to `modulus`. /// ## modulus /// The modulus which defines the residue ring Z mod `modulus` /// in which the multiplicative order of `generator` is being estimated. /// ## power /// Power of `generator` by which `target` is multiplied. /// ## target /// Register interpreted as little endian encoded which is multiplied by /// given power of the generator. The multiplication is performed modulo /// `modulus`. internal operation ApplyOrderFindingOracle( generator : Int, modulus : Int, power : Int, target : Qubit[] ) : Unit is Adj + Ctl { // The oracle we use for order finding implements |x⟩ ↦ |x⋅a mod N⟩. We // also use `ExpModI` to compute a by which x must be multiplied. Also // note that we interpret target as unsigned integer in little-endian // encoding. ModularMultiplyByConstant(modulus, ExpModI(generator, power, modulus), target); } /// # Summary /// Performs modular in-place multiplication by a classical constant. /// /// # Description /// Given the classical constants `c` and `modulus`, and an input /// quantum register |𝑦⟩, this operation /// computes `(c*x) % modulus` into |𝑦⟩. /// /// # Input /// ## modulus /// Modulus to use for modular multiplication /// ## c /// Constant by which to multiply |𝑦⟩ /// ## y /// Quantum register of target internal operation ModularMultiplyByConstant(modulus : Int, c : Int, y : Qubit[]) : Unit is Adj + Ctl { use qs = Qubit[Length(y)]; for (idx, yq) in Enumerated(y) { let shiftedC = (c <<< idx) % modulus; Controlled ModularAddConstant([yq], (modulus, shiftedC, qs)); } ApplyToEachCA(SWAP, Zipped(y, qs)); let invC = InverseModI(c, modulus); for (idx, yq) in Enumerated(y) { let shiftedC = (invC <<< idx) % modulus; Controlled ModularAddConstant([yq], (modulus, modulus - shiftedC, qs)); } } /// # Summary /// Performs modular in-place addition of a classical constant into a /// quantum register. /// /// # Description /// Given the classical constants `c` and `modulus`, and an input /// quantum register |𝑦⟩, this operation /// computes `(x+c) % modulus` into |𝑦⟩. /// /// # Input /// ## modulus /// Modulus to use for modular addition /// ## c /// Constant to add to |𝑦⟩ /// ## y /// Quantum register of target internal operation ModularAddConstant(modulus : Int, c : Int, y : Qubit[]) : Unit is Adj + Ctl { body (...) { Controlled ModularAddConstant([], (modulus, c, y)); } controlled (ctrls, ...) { // We apply a custom strategy to control this operation instead of // letting the compiler create the controlled variant for us in which // the `Controlled` functor would be distributed over each operation // in the body. // // Here we can use some scratch memory to save ensure that at most one // control qubit is used for costly operations such as `AddConstant` // and `CompareGreaterThenOrEqualConstant`. if Length(ctrls) >= 2 { use control = Qubit(); within { Controlled X(ctrls, control); } apply { Controlled ModularAddConstant([control], (modulus, c, y)); } } else { use carry = Qubit(); Controlled AddConstant(ctrls, (c, y + [carry])); Controlled Adjoint AddConstant(ctrls, (modulus, y + [carry])); Controlled AddConstant([carry], (modulus, y)); Controlled CompareGreaterThanOrEqualConstant(ctrls, (c, y, carry)); } } } /// # Summary /// Performs in-place addition of a constant into a quantum register. /// /// # Description /// Given a non-empty quantum register |𝑦⟩ of length 𝑛+1 and a positive /// constant 𝑐 < 2ⁿ, computes |𝑦 + c⟩ into |𝑦⟩. /// /// # Input /// ## c /// Constant number to add to |𝑦⟩. /// ## y /// Quantum register of second summand and target; must not be empty. internal operation AddConstant(c : Int, y : Qubit[]) : Unit is Adj + Ctl { // We are using this version instead of the library version that is based // on Fourier angles to show an advantage of sparse simulation in this sample. let n = Length(y); Fact(n > 0, "Bit width must be at least 1"); Fact(c >= 0, "constant must not be negative"); Fact(c < 2 ^ n, $"constant must be smaller than {2L ^ n}"); if c != 0 { // If c has j trailing zeroes than the j least significant bits // of y will not be affected by the addition and can therefore be // ignored by applying the addition only to the other qubits and // shifting c accordingly. let j = NTrailingZeroes(c); use x = Qubit[n - j]; within { ApplyXorInPlace(c >>> j, x); } apply { IncByLE(x, y[j...]); } } } /// # Summary /// Performs greater-than-or-equals comparison to a constant. /// /// # Description /// Toggles output qubit `target` if and only if input register `x` /// is greater than or equal to `c`. /// /// # Input /// ## c /// Constant value for comparison. /// ## x /// Quantum register to compare against. /// ## target /// Target qubit for comparison result. /// /// # Reference /// This construction is described in [Lemma 3, arXiv:2201.10200] internal operation CompareGreaterThanOrEqualConstant(c : Int, x : Qubit[], target : Qubit) : Unit is Adj+Ctl { let bitWidth = Length(x); if c == 0 { X(target); } elif c >= 2 ^ bitWidth { // do nothing } elif c == 2 ^ (bitWidth - 1) { ApplyLowTCNOT(Tail(x), target); } else { // normalize constant let l = NTrailingZeroes(c); let cNormalized = c >>> l; let xNormalized = x[l...]; let bitWidthNormalized = Length(xNormalized); let gates = Rest(IntAsBoolArray(cNormalized, bitWidthNormalized)); use qs = Qubit[bitWidthNormalized - 1]; let cs1 = [Head(xNormalized)] + Most(qs); let cs2 = Rest(xNormalized); within { for i in IndexRange(gates) { (gates[i] ? ApplyAnd | ApplyOr)(cs1[i], cs2[i], qs[i]); } } apply { ApplyLowTCNOT(Tail(qs), target); } } } /// # Summary /// Internal operation used in the implementation of GreaterThanOrEqualConstant. internal operation ApplyOr(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj { within { ApplyToEachA(X, [control1, control2]); } apply { ApplyAnd(control1, control2, target); X(target); } } internal operation ApplyAnd(control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj { body (...) { CCNOT(control1, control2, target); } adjoint (...) { H(target); if (M(target) == One) { X(target); CZ(control1, control2); } } } /// # Summary /// Returns the number of trailing zeroes of a number /// /// ## Example /// ```qsharp /// let zeroes = NTrailingZeroes(21); // = NTrailingZeroes(0b1101) = 0 /// let zeroes = NTrailingZeroes(20); // = NTrailingZeroes(0b1100) = 2 /// ``` internal function NTrailingZeroes(number : Int) : Int { mutable nZeroes = 0; mutable copy = number; while (copy % 2 == 0) { set nZeroes += 1; set copy /= 2; } return nZeroes; } /// # Summary /// An implementation for `CNOT` that when controlled using a single control uses /// a helper qubit and uses `ApplyAnd` to reduce the T-count to 4 instead of 7. internal operation ApplyLowTCNOT(a : Qubit, b : Qubit) : Unit is Adj+Ctl { body (...) { CNOT(a, b); } adjoint self; controlled (ctls, ...) { // In this application this operation is used in a way that // it is controlled by at most one qubit. Fact(Length(ctls) <= 1, "At most one control line allowed"); if IsEmpty(ctls) { CNOT(a, b); } else { use q = Qubit(); within { ApplyAnd(Head(ctls), a, q); } apply { CNOT(q, b); } } } controlled adjoint self; }
Estimación del algoritmo cuántico
Ahora, calcula los recursos físicos de la RunProgram
operación con las suposiciones predeterminadas. Agregue una nueva celda y copie el código siguiente.
result = qsharp.estimate("RunProgram()")
result
La qsharp.estimate
función crea un objeto de resultado, que se puede usar para mostrar una tabla con los recuentos generales de recursos físicos. Se pueden inspeccionar los detalles de los costos contrayendo los grupos, que contienen más información. Para obtener más información, consulte los datos completos del informe del estimador de recursos.
Por ejemplo, contraiga el grupo Parámetros cuánticos lógicos para ver que la distancia del código es 21 y el número de cúbits físicos es 882.
Parámetro de cúbit lógico | Valor |
---|---|
Esquema de QEC | surface_code |
Distancia del código | 21 |
Cúbits físicos | 882 |
Tiempo del ciclo lógico | 8 milisecs |
Tasa de errores de cúbit lógico | 3.00E-13 |
Cruce del prefactor | 0,03 |
Umbral de corrección de errores | 0,01 |
Fórmula de tiempo del ciclo lógico | (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime ) * codeDistance |
Fórmula de cúbits físicos | 2 * codeDistance * codeDistance |
Sugerencia
Para una versión más compacta de la tabla de salida, puede usar result.summary
.
Diagrama de espacio
La distribución de cúbits físicos usados para el algoritmo y las factorías de T es un factor que puede afectar al diseño del algoritmo. Puede usar el qsharp-widgets
paquete para visualizar esta distribución para comprender mejor los requisitos de espacio estimados para el algoritmo.
from qsharp-widgets import SpaceChart, EstimateDetails
SpaceChart(result)
En este ejemplo, el número de cúbits físicos necesarios para ejecutar el algoritmo se 829766, 196686 de los cuales son cúbits de algoritmo y 633080 de los cuales son cúbits de fábrica de T.
Cambiar los valores predeterminados y calcular el algoritmo
Al enviar una solicitud de estimación de recursos para el programa, puede especificar algunos parámetros opcionales. Use el jobParams
campo para tener acceso a todos los target parámetros que se pueden pasar a la ejecución del trabajo y ver qué valores predeterminados se han asumido:
result['jobParams']
{'errorBudget': 0.001,
'qecScheme': {'crossingPrefactor': 0.03,
'errorCorrectionThreshold': 0.01,
'logicalCycleTime': '(4 * twoQubitGateTime + 2 * oneQubitMeasurementTime) * codeDistance',
'name': 'surface_code',
'physicalQubitsPerLogicalQubit': '2 * codeDistance * codeDistance'},
'qubitParams': {'instructionSet': 'GateBased',
'name': 'qubit_gate_ns_e3',
'oneQubitGateErrorRate': 0.001,
'oneQubitGateTime': '50 ns',
'oneQubitMeasurementErrorRate': 0.001,
'oneQubitMeasurementTime': '100 ns',
'tGateErrorRate': 0.001,
'tGateTime': '50 ns',
'twoQubitGateErrorRate': 0.001,
'twoQubitGateTime': '50 ns'}}
Puede ver que el estimador de recursos toma el qubit_gate_ns_e3
modelo de cúbits, el surface_code
código de corrección de errores y el presupuesto de errores 0,001 como valores predeterminados para la estimación.
Estos son los target parámetros que se pueden personalizar:
errorBudget
: el presupuesto general de errores permitido para el algoritmo.qecScheme
: el esquema de corrección de errores cuánticos (QEC)qubitParams
: los parámetros de cúbit físicoconstraints
: restricciones en el nivel de componente.distillationUnitSpecifications
: las especificaciones de los algoritmos de destilación de fábricas de T.estimateType
- una o frontera
Para obtener más información, consulte Parámetros de destino para el estimador de recursos.
Cambio del modelo de cúbits
Puede calcular el costo del mismo algoritmo mediante el parámetro de cúbit basado en Majorana, qubitParams
, "qubit_maj_ns_e6".
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
}})
EstimateDetails(result_maj)
Cambio del esquema de corrección de errores cuánticos
Puede volver a ejecutar el trabajo de estimación de recursos para el mismo ejemplo en los parámetros de cúbit basados en Majorana con un esquema QEC floqued, qecScheme
.
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
},
"qecScheme": {
"name": "floquet_code"
}})
EstimateDetails(result_maj)
Cambio del presupuesto de errores
A continuación, vuelva a ejecutar el mismo circuito cuántico con un errorBudget
10 %.
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
},
"qecScheme": {
"name": "floquet_code"
},
"errorBudget": 0.1})
EstimateDetails(result_maj)
Procesamiento por lotes con el estimador de recursos
El estimador de recursos de Azure Quantum permite ejecutar varias configuraciones de target parámetros y comparar los resultados. Esto resulta útil cuando desea comparar el costo de diferentes modelos de cúbits, esquemas QEC o presupuestos de errores.
Puede realizar una estimación por lotes pasando una lista de target parámetros al
params
parámetro de laqsharp.estimate
función. Por ejemplo, ejecute el mismo algoritmo con los parámetros predeterminados y los parámetros de cúbit basados en Majorana con un esquema QEC floqued.result_batch = qsharp.estimate("RunProgram()", params= [{}, # Default parameters { "qubitParams": { "name": "qubit_maj_ns_e6" }, "qecScheme": { "name": "floquet_code" } }]) result_batch.summary_data_frame(labels=["Gate-based ns, 10⁻³", "Majorana ns, 10⁻⁶"])
Modelo Cúbits lógicos Profundidad lógica Estados T Distancia del código Generadores de T Fracción de generador de T Cúbits físicos rQOPS Tiempo de ejecución físico ns basados en puertas, 10⁻³ 223 3,64 M 4,70 M 21 19 76.30 % 829.77k 26,55 M 31 segundos ns basados en Majorana, 10⁻⁶ 223 3,64 M 4,70 M 5 19 63.02 % 79.60k 148.67M 5 segundos También puede construir una lista de parámetros de estimación mediante la
EstimatorParams
clase .from qsharp.estimator import EstimatorParams, QubitParams, QECScheme, LogicalCounts labels = ["Gate-based µs, 10⁻³", "Gate-based µs, 10⁻⁴", "Gate-based ns, 10⁻³", "Gate-based ns, 10⁻⁴", "Majorana ns, 10⁻⁴", "Majorana ns, 10⁻⁶"] params = EstimatorParams(num_items=6) params.error_budget = 0.333 params.items[0].qubit_params.name = QubitParams.GATE_US_E3 params.items[1].qubit_params.name = QubitParams.GATE_US_E4 params.items[2].qubit_params.name = QubitParams.GATE_NS_E3 params.items[3].qubit_params.name = QubitParams.GATE_NS_E4 params.items[4].qubit_params.name = QubitParams.MAJ_NS_E4 params.items[4].qec_scheme.name = QECScheme.FLOQUET_CODE params.items[5].qubit_params.name = QubitParams.MAJ_NS_E6 params.items[5].qec_scheme.name = QECScheme.FLOQUET_CODE
qsharp.estimate("RunProgram()", params=params).summary_data_frame(labels=labels)
Modelo Cúbits lógicos Profundidad lógica Estados T Distancia del código Generadores de T Fracción de generador de T Cúbits físicos rQOPS Tiempo de ejecución físico μs basados en puertas, 10⁻³ 223 3,64 M 4,70 M 17 13 40.54 % 216.77k 21.86k 10 horas μs basados en puertas, 10⁻⁴ 223 3,64 M 4,70 M 9 14 43.17 % 63.57k 41.30 000 5 horas ns basados en puertas, 10⁻³ 223 3,64 M 4,70 M 17 16 69.08 % 416.89k 32,79 M 25 segundos ns basados en puertas, 10⁻⁴ 223 3,64 M 4,70 M 9 14 43.17 % 63.57k 61,94 M 13 segundos ns basados en Majorana, 10⁻⁴ 223 3,64 M 4,70 M 9 19 82.75 % 501.48k 82,59 M 10 segundos ns basados en Majorana, 10⁻⁶ 223 3,64 M 4,70 M 5 13 31.47 % 42.96k 148.67M 5 segundos
Ejecución de la estimación de pareto frontier
Al calcular los recursos de un algoritmo, es importante tener en cuenta el equilibrio entre el número de cúbits físicos y el tiempo de ejecución del algoritmo. Podría considerar la asignación de tantos cúbits físicos como sea posible para reducir el tiempo de ejecución del algoritmo. Sin embargo, el número de cúbits físicos está limitado por el número de cúbits físicos disponibles en el hardware cuántico.
La estimación de la frontera de Pareto proporciona varias estimaciones para el mismo algoritmo, cada una con un equilibrio entre el número de cúbits y el tiempo de ejecución.
Para ejecutar el estimador de recursos mediante la estimación de frontera de Pareto, debe especificar el
"estimateType"
target parámetro como"frontier"
. Por ejemplo, ejecute el mismo algoritmo con los parámetros de cúbit basados en Majorana con un código de superficie mediante la estimación de frontera de Pareto.result = qsharp.estimate("RunProgram()", params= {"qubitParams": { "name": "qubit_maj_ns_e4" }, "qecScheme": { "name": "surface_code" }, "estimateType": "frontier", # frontier estimation } )
Puede usar la
EstimatesOverview
función para mostrar una tabla con los recuentos generales de recursos físicos. Haga clic en el icono situado junto a la primera fila para seleccionar las columnas que desea mostrar. Puede seleccionar entre el nombre de ejecución, el tipo de estimación, el tipo de cúbit, el esquema qec, el presupuesto de errores, los cúbits lógicos, la profundidad lógica, la distancia de código, los estados de T, las factorías de T, la fracción de fábrica de T, el runtime, rQOPS y los cúbits físicos.from qsharp_widgets import EstimatesOverview EstimatesOverview(result)
En la columna Tipo estimado de la tabla de resultados, puede ver el número de combinaciones diferentes de {número de cúbits, runtime} para el algoritmo. En este caso, el estimador de recursos encuentra 22 combinaciones óptimas diferentes de muchos miles de posibles.
Diagrama de tiempo espaciador
La EstimatesOverview
función también muestra el diagrama de tiempo espaciador del estimador de recursos.
El diagrama de tiempo espaciado muestra el número de cúbits físicos y el tiempo de ejecución del algoritmo para cada par {número de cúbits, tiempo de ejecución}. Puede mantener el puntero sobre cada punto para ver los detalles de la estimación de recursos en ese momento.
Procesamiento por lotes con estimación de frontera de Pareto
Para calcular y comparar varias configuraciones de target parámetros con estimación de frontera, agregue
"estimateType": "frontier",
a los parámetros.result = qsharp.estimate( "RunProgram()", [ { "qubitParams": { "name": "qubit_maj_ns_e4" }, "qecScheme": { "name": "surface_code" }, "estimateType": "frontier", # Pareto frontier estimation }, { "qubitParams": { "name": "qubit_maj_ns_e6" }, "qecScheme": { "name": "floquet_code" }, "estimateType": "frontier", # Pareto frontier estimation }, ] ) EstimatesOverview(result, colors=["#1f77b4", "#ff7f0e"], runNames=["e4 Surface Code", "e6 Floquet Code"])
Nota
Puede definir colores y nombres de ejecución para el diagrama de tiempo de cúbit mediante la
EstimatesOverview
función .Al ejecutar varias configuraciones de target parámetros mediante la estimación de frontera de Pareto, puede ver las estimaciones de recursos para un punto específico del diagrama de tiempo de espacio, es decir, para cada par {número de cúbits, tiempo de ejecución}. Por ejemplo, el código siguiente muestra el uso de los detalles de estimación para la segunda ejecución (estimate index=0) y el cuarto tiempo de ejecución más corto (point index=3).
EstimateDetails(result[1], 4)
También puede ver el diagrama de espacio para un punto específico del diagrama de tiempo espacial. Por ejemplo, el código siguiente muestra el diagrama de espacio para la primera ejecución de combinaciones (estimación de index=0) y el tercer tiempo de ejecución más corto (point index=2).
SpaceChart(result[0], 2)
Requisitos previos para Qiskit
- Una cuenta de Azure con una suscripción activa. Si no tiene una cuenta de Azure, regístrese de forma gratuita y regístrese para obtener una suscripción de pago por uso.
- Un área de trabajo de Azure Quantum. Para más información, consulte Creación de un área de trabajo de Azure Quantum.
Habilitación del estimador target de recursos de Azure Quantum en el área de trabajo
El estimador de recursos es un target proveedor de computación cuántica de Microsoft. Si ha creado un área de trabajo desde el lanzamiento del estimador de recursos, el proveedor de computación cuántica de Microsoft se agregó automáticamente al área de trabajo.
Si usa un área de trabajo de Azure Quantum existente :
- Abra el área de trabajo en Azure Portal.
- En el panel de la izquierda, en Operaciones, seleccione Proveedores.
- Seleccione + Agregar un proveedor.
- Seleccione + Agregar en Computación cuántica de Microsoft.
- Seleccione Learn & Desarrollar y seleccione Agregar.
Creación de un cuaderno en el área de trabajo
- Inicie sesión en Azure Portal y seleccione el área de trabajo de Azure Quantum.
- En Operaciones, seleccione Cuadernos.
- Haga clic en Mis cuadernos y haga clic en Agregar nuevo.
- En Tipo de kernel, seleccione IPython.
- Escriba un nombre para el archivo y haga clic en Create archivo.
Cuando se abre el cuaderno nuevo, este crea automáticamente el código de la primera celda, en función de la información de la suscripción y del área de trabajo.
from azure.quantum import Workspace
workspace = Workspace (
resource_id = "", # Your resource_id
location = "" # Your workspace location (for example, "westus")
)
Nota
A menos que se indique lo contrario, debe ejecutar cada celda en orden a medida que se cree para evitar problemas de compilación.
Haga clic en el icono triangular "reproducir" situado a la izquierda de la celda para ejecutar el código.
Carga de las importaciones necesarias
En primer lugar, deberá importar módulos adicionales de azure-quantum y qiskit
.
Haga clic en + Código para agregar una nueva celda y, a continuación, agregue y ejecute el código siguiente:
from azure.quantum.qiskit import AzureQuantumProvider
from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import RGQFTMultiplier
Conexión al servicio Azure Quantum
A continuación, cree un objeto AzureQuantumProvider mediante el workspace
objeto de la celda anterior para conectarse al área de trabajo de Azure Quantum. Cree una instancia de back-end y establezca el estimador de recursos como target.
provider = AzureQuantumProvider(workspace)
backend = provider.get_backend('microsoft.estimator')
Create el algoritmo cuántico
En este ejemplo, se crea un circuito cuántico para un multiplicador basado en la construcción presentada en Ruiz-Perez y Garcia-Escartin (arXiv:1411.5949) que usa la transformación Quantum Fourier para implementar aritmética.
Puede ajustar el tamaño del multiplicador cambiando la bitwidth
variable. La generación del circuito se ajusta en una función a la que se puede llamar con el bitwidth
valor del multiplicador. La operación tendrá dos registros de entrada, cada uno del tamaño del especificado bitwidth
y un registro de salida que sea el doble del tamaño del especificado bitwidth
. La función también imprimirá algunos recuentos de recursos lógicos para el multiplicador extraído directamente del circuito cuántico.
def create_algorithm(bitwidth):
print(f"[INFO] Create a QFT-based multiplier with bitwidth {bitwidth}")
# Print a warning for large bitwidths that will require some time to generate and
# transpile the circuit.
if bitwidth > 18:
print(f"[WARN] It will take more than one minute generate a quantum circuit with a bitwidth larger than 18")
circ = RGQFTMultiplier(num_state_qubits=bitwidth, num_result_qubits=2 * bitwidth)
# One could further reduce the resource estimates by increasing the optimization_level,
# however, this will also increase the runtime to construct the algorithm. Note, that
# it does not affect the runtime for resource estimation.
print(f"[INFO] Decompose circuit into intrinsic quantum operations")
circ = transpile(circ, basis_gates=SUPPORTED_INSTRUCTIONS, optimization_level=0)
# print some statistics
print(f"[INFO] qubit count: {circ.num_qubits}")
print("[INFO] gate counts")
for gate, count in circ.count_ops().items():
print(f"[INFO] - {gate}: {count}")
return circ
Nota
Puede enviar trabajos de estimación de recursos físicos para algoritmos que no tengan estados T, pero que tengan al menos una medida.
Estimación del algoritmo cuántico
Create una instancia del algoritmo mediante la create_algorithm
función . Puede ajustar el tamaño del multiplicador cambiando la bitwidth
variable.
bitwidth = 4
circ = create_algorithm(bitwidth)
Calcule los recursos físicos de esta operación con las suposiciones predeterminadas. Puede enviar el circuito al back-end del estimador de recursos mediante el run
método y, a continuación, ejecutar job.result()
para esperar a que el trabajo se complete y devuelva los resultados.
job = backend.run(circ)
result = job.result()
result
Esto crea una tabla que muestra los recuentos generales de recursos físicos. Se pueden inspeccionar los detalles de los costos contrayendo los grupos, que contienen más información.
Sugerencia
Para una versión más compacta de la tabla de salida, puede usar result.summary
.
Por ejemplo, si contrae el grupo Parámetros de cúbit lógico , puede ver más fácilmente que la distancia del código de corrección de errores es 15.
Parámetro de cúbit lógico | Valor |
---|---|
Esquema de QEC | surface_code |
Distancia del código | 15 |
Cúbits físicos | 450 |
Tiempo del ciclo lógico | 6us |
Tasa de errores de cúbit lógico | 3.00E-10 |
Cruce del prefactor | 0,03 |
Umbral de corrección de errores | 0,01 |
Fórmula de tiempo del ciclo lógico | (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime ) * codeDistance |
Fórmula de cúbits físicos | 2 * codeDistance * codeDistance |
En el grupo Parámetros de cúbit físico , puede ver las propiedades de cúbit físicos que se han asumido para esta estimación. Por ejemplo, el tiempo para realizar una medición de un solo cúbit y una puerta de un solo cúbit se supone que son 100 ns y 50 ns, respectivamente.
Sugerencia
También puede acceder a la salida del estimador de recursos como diccionario de Python mediante el método result.data().
Para obtener más información, consulte la lista completa de datos de salida del estimador de recursos.
Diagramas de espacio
La distribución de cúbits físicos usados para el algoritmo y las factorías de T es un factor que puede afectar al diseño del algoritmo. Puede visualizar esta distribución para comprender mejor los requisitos de espacio estimados para el algoritmo.
result.diagram.space
El diagrama de espacio muestra la proporción de cúbits de algoritmo y cúbits de fábrica de T. Tenga en cuenta que el número de copias de fábrica de T, 28, contribuye al número de cúbits físicos para factorías de T como $\text{T factorys} \cdot \text{qubit físico por factoría de T}= 28 \cdot 18 000 = 504 000$.
Para más información, consulte Estimación física de fábrica de T.
Cambiar los valores predeterminados y calcular el algoritmo
Al enviar una solicitud de estimación de recursos para el programa, puede especificar algunos parámetros opcionales. Use el jobParams
campo para tener acceso a todos los valores que se pueden pasar a la ejecución del trabajo y ver qué valores predeterminados se han asumido:
result.data()["jobParams"]
{'errorBudget': 0.001,
'qecScheme': {'crossingPrefactor': 0.03,
'errorCorrectionThreshold': 0.01,
'logicalCycleTime': '(4 * twoQubitGateTime + 2 * oneQubitMeasurementTime) * codeDistance',
'name': 'surface_code',
'physicalQubitsPerLogicalQubit': '2 * codeDistance * codeDistance'},
'qubitParams': {'instructionSet': 'GateBased',
'name': 'qubit_gate_ns_e3',
'oneQubitGateErrorRate': 0.001,
'oneQubitGateTime': '50 ns',
'oneQubitMeasurementErrorRate': 0.001,
'oneQubitMeasurementTime': '100 ns',
'tGateErrorRate': 0.001,
'tGateTime': '50 ns',
'twoQubitGateErrorRate': 0.001,
'twoQubitGateTime': '50 ns'}}
Estos son los target parámetros que se pueden personalizar:
errorBudget
: el presupuesto de errores permitido general.qecScheme
: el esquema de corrección de errores cuánticos (QEC)qubitParams
: los parámetros de cúbit físicoconstraints
: restricciones en el nivel de componente.distillationUnitSpecifications
: las especificaciones de los algoritmos de destilación de fábricas de T
Para obtener más información, consulte Parámetros de destino para el estimador de recursos.
Cambio del modelo de cúbits
A continuación, calcule el costo del mismo algoritmo mediante el parámetro de cúbit basado en Majorana. qubit_maj_ns_e6
job = backend.run(circ,
qubitParams={
"name": "qubit_maj_ns_e6"
})
result = job.result()
result
Puede inspeccionar los recuentos físicos mediante programación. Por ejemplo, puede explorar los detalles sobre la factoría de T que se creó para ejecutar el algoritmo.
result.data()["tfactory"]
{'eccDistancePerRound': [1, 1, 5],
'logicalErrorRate': 1.6833177305222897e-10,
'moduleNamePerRound': ['15-to-1 space efficient physical',
'15-to-1 RM prep physical',
'15-to-1 RM prep logical'],
'numInputTstates': 20520,
'numModulesPerRound': [1368, 20, 1],
'numRounds': 3,
'numTstates': 1,
'physicalQubits': 16416,
'physicalQubitsPerRound': [12, 31, 1550],
'runtime': 116900.0,
'runtimePerRound': [4500.0, 2400.0, 110000.0]}
Nota
De forma predeterminada, el tiempo de ejecución se muestra en nanosegundos.
Puede usar estos datos para generar algunas explicaciones de cómo las factorías de T producen los estados T necesarios.
data = result.data()
tfactory = data["tfactory"]
breakdown = data["physicalCounts"]["breakdown"]
producedTstates = breakdown["numTfactories"] * breakdown["numTfactoryRuns"] * tfactory["numTstates"]
print(f"""A single T factory produces {tfactory["logicalErrorRate"]:.2e} T states with an error rate of (required T state error rate is {breakdown["requiredLogicalTstateErrorRate"]:.2e}).""")
print(f"""{breakdown["numTfactories"]} copie(s) of a T factory are executed {breakdown["numTfactoryRuns"]} time(s) to produce {producedTstates} T states ({breakdown["numTstates"]} are required by the algorithm).""")
print(f"""A single T factory is composed of {tfactory["numRounds"]} rounds of distillation:""")
for round in range(tfactory["numRounds"]):
print(f"""- {tfactory["numModulesPerRound"][round]} {tfactory["moduleNamePerRound"][round]} unit(s)""")
A single T factory produces 1.68e-10 T states with an error rate of (required T state error rate is 2.77e-08).
23 copies of a T factory are executed 523 time(s) to produce 12029 T states (12017 are required by the algorithm).
A single T factory is composed of 3 rounds of distillation:
- 1368 15-to-1 space efficient physical unit(s)
- 20 15-to-1 RM prep physical unit(s)
- 1 15-to-1 RM prep logical unit(s)
Cambio del esquema de corrección de errores cuánticos
Ahora, vuelva a ejecutar el trabajo de estimación de recursos para el mismo ejemplo en los parámetros de cúbit basados en Majorana con un esquema QEC floqued, qecScheme
.
job = backend.run(circ,
qubitParams={
"name": "qubit_maj_ns_e6"
},
qecScheme={
"name": "floquet_code"
})
result_maj_floquet = job.result()
result_maj_floquet
Cambio del presupuesto de errores
Vamos a volver a ejecutar el mismo circuito cuántico con un errorBudget
10 %.
job = backend.run(circ,
qubitParams={
"name": "qubit_maj_ns_e6"
},
qecScheme={
"name": "floquet_code"
},
errorBudget=0.1)
result_maj_floquet_e1 = job.result()
result_maj_floquet_e1
Nota
Si tiene algún problema al trabajar con el estimador de recursos, consulte la página Solución de problemas o póngase en contacto con AzureQuantumInfo@microsoft.com.
Pasos siguientes
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente GitHub Issues como mecanismo de comentarios sobre el contenido y lo sustituiremos por un nuevo sistema de comentarios. Para más información, vea:Enviar y ver comentarios de