Différentes façons d’exécuter l’estimateur de ressources
Dans cet article, vous allez apprendre à utiliser l’estimateur de ressources Azure Quantum. L’estimateur de ressources est disponible à la fois dans VS Code et en ligne dans Portail Azure.
Le tableau suivant montre les différentes façons d’exécuter l’estimateur de ressources.
Scénario utilisateur | Plateforme | Didacticiel |
---|---|---|
Estimer les ressources d’un programme Q# | Visual Studio Code | Sélectionnez Q# dans VS Code en haut de la page. |
Estimer les ressources d’un programme Q# (avancé) | Jupyter Notebook dans Visual Studio Code | Sélectionnez Q# dans Jupyter Notebook en haut de la page |
Estimer les ressources d’un programme Qiskit | Portail Azure Quantum | Sélectionnez Qiskit dans Portail Azure en haut de la page. |
Estimer les ressources d’un programme QIR | Portail Azure Quantum | Envoyer QIR |
Utiliser des fichiers FCIDUMP comme paramètres d’argument (avancé) | Visual Studio Code | Soumettre un problème de chimie quantique |
Notes
Le Kit de développement Microsoft Quantum (QDK classique) ne sera plus pris en charge après le 30 juin 2024. Si vous êtes un développeur QDK existant, nous vous recommandons de passer au nouveau Kit de développement Azure Quantum (QDK moderne) pour continuer à développer des solutions quantiques. Pour plus d’informations, consultez Migrer votre code Q# vers le QDK moderne.
Conditions préalables pour VS Code
- La dernière version de Visual Studio Code ou ouvrez VS Code sur le web.
- Dernière version de l’extension du Kit de développement Azure Quantum . Pour plus d’informations sur l’installation, consultez Installation du QDK moderne sur VS Code.
Conseil
Vous n’avez pas besoin d’un compte Azure pour exécuter l’estimateur de ressources local.
Créer un fichier Q#
- Ouvrez Visual Studio Code et sélectionnez Fichier > Nouveau fichier texte pour créer un fichier.
- Enregistrez le fichier sous le nom
ShorRE.qs
. Ce fichier contient le code Q# de votre programme.
Créer l’algorithme quantique
Copiez le code suivant dans le fichier 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;
}
}
Exécuter l’estimateur de ressources
L’estimateur de ressources propose six paramètres de qubit prédéfinis, dont quatre ont des jeux d’instructions basés sur des portes et deux qui ont un jeu d’instructions Majorana. Il offre également deux codes de correction d’erreur quantique, surface_code
et floquet_code
.
Dans cet exemple, vous exécutez l’estimateur de ressources à l’aide du qubit_gate_us_e3
paramètre qubit et du surface_code
code de correction d’erreur quantique.
- Sélectionnez Affichage -> Palette de commandes, ou appuyez sur Ctrl+Maj+P, puis tapez « ressource » qui doit faire apparaître l’option Q# : Calculer les estimations des ressources . Sélectionnez cette option pour ouvrir la fenêtre Estimateur de ressources.
- Vous pouvez sélectionner un ou plusieurs paramètres Qubit + types de code correction d’erreur pour estimer les ressources. Pour cet exemple, sélectionnez qubit_gate_us_e3 , puis cliquez sur OK.
- Spécifiez le budget d’erreur ou acceptez la valeur par défaut 0,001. Pour cet exemple, conservez la valeur par défaut et appuyez sur Entrée.
- Appuyez sur Entrée pour accepter le nom de résultat par défaut basé sur le nom de fichier, dans ce cas, ShorRE.
Afficher les résultats
L’estimateur de ressources fournit plusieurs estimations pour le même algorithme, chacune affichant des compromis entre le nombre de qubits et le runtime. Comprendre le compromis entre l’exécution et la mise à l’échelle du système est l’un des aspects les plus importants de l’estimation des ressources.
Le résultat de l’estimation des ressources s’affiche dans la fenêtre Estimation Q# .
L’onglet Résultats affiche un résumé de l’estimation des ressources. Cliquez sur l’icône en regard de la première ligne pour sélectionner les colonnes que vous souhaitez afficher. Vous pouvez sélectionner un nom d’exécution, un type d’estimation, un type qubit, un schéma qec, un budget d’erreur, des qubits logiques, une profondeur logique, une distance de code, des états T, des fabriques T, une fraction de fabrique T, un runtime, des rQOPS et des qubits physiques.
Dans la colonne Type d’estimation de la table de résultats, vous pouvez voir le nombre de combinaisons optimales de {nombre de qubits, runtime} pour votre algorithme. Ces combinaisons sont visibles dans le diagramme de l’espace-temps.
Le diagramme espace-temps montre les compromis entre le nombre de qubits physiques et le runtime de l’algorithme. Dans ce cas, l’estimateur de ressources trouve 13 combinaisons optimales différentes parmi plusieurs milliers de combinaisons possibles. Vous pouvez pointer sur chaque point {nombre de qubits, runtime} pour afficher les détails de l’estimation des ressources à ce stade.
Pour plus d’informations, consultez Diagramme de l’espace-temps.
Notes
Vous devez cliquer sur un point du diagramme espace-temps, c’est-à-dire une paire {nombre de qubits, runtime}, pour afficher le diagramme d’espace et les détails de l’estimation des ressources correspondant à ce point.
Le diagramme d’espace montre la distribution des qubits physiques utilisés pour l’algorithme et les fabriques T, correspondant à une paire {nombre de qubits, runtime}. Par exemple, si vous sélectionnez le point le plus à gauche dans le diagramme de l’espace-temps, le nombre de qubits physiques requis pour exécuter l’algorithme est 427726, 196686 sont des qubits d’algorithme et 231040 dont des qubits T factory.
Enfin, l’onglet Estimations des ressources affiche la liste complète des données de sortie pour l’estimateur de ressources correspondant à une paire {nombre de qubits, runtime} . Vous pouvez examiner les détails des coûts en réduisant les groupes, qui ont plus d’informations. Par exemple, sélectionnez le point le plus à gauche dans le diagramme d’espace-temps et réduisez le groupe Paramètres de qubit logique .
Paramètre qubit logique Valeur Schéma QEC surface_code Distance du code 21 Qubits physiques 882 Durée du cycle logique 13 milisecs Taux d’erreur de qubit logique 3.00E-13 Préfacteur de croisement 0,03 Seuil de correction d’erreur 0,01 Formule de temps de cycle logique (4 * twoQubitGateTime
+ 2 *oneQubitMeasurementTime
) *codeDistance
Formule de qubits physiques 2 * codeDistance
*codeDistance
Conseil
Cliquez sur Afficher les lignes détaillées pour afficher la description de chaque sortie des données du rapport.
Pour plus d’informations, consultez les données de rapport complètes de l’estimateur de ressources.
Modifier les target paramètres
Vous pouvez estimer le coût du même programme Q# à l’aide d’un autre type de qubit, d’un code de correction d’erreur et d’un budget d’erreur. Ouvrez la fenêtre Estimateur de ressources en sélectionnant Affichage -> Palette de commandes, puis tapez Q#: Calculate Resource Estimates
.
Sélectionnez une autre configuration, par exemple le paramètre qubit basé sur Majorana, qubit_maj_ns_e6
. Acceptez la valeur budgétaire d’erreur par défaut ou entrez une nouvelle valeur, puis appuyez sur Entrée. L’estimateur de ressources réexécutera l’estimation avec les nouveaux target paramètres.
Pour plus d’informations, consultez Paramètres cibles pour l’estimateur de ressources.
Exécuter plusieurs configurations de paramètres
L’estimateur de ressources Azure Quantum peut exécuter plusieurs configurations de target paramètres et comparer les résultats de l’estimation des ressources.
Sélectionnez Affichage -> Palette de commandes, ou appuyez sur Ctrl+Maj+P, puis tapez
Q#: Calculate Resource Estimates
.Sélectionnez qubit_gate_us_e3, qubit_gate_us_e4, qubit_maj_ns_e4 + floquet_code et qubit_maj_ns_e6 + floquet_code, puis cliquez sur OK.
Acceptez la valeur budgétaire d’erreur par défaut 0,001 et appuyez sur Entrée.
Appuyez sur Entrée pour accepter le fichier d’entrée, dans ce cas, ShorRE.qs.
Dans le cas de plusieurs configurations de paramètres, les résultats sont affichés dans différentes lignes sous l’onglet Résultats .
Le diagramme Espace-temps montre les résultats de toutes les configurations de paramètres. La première colonne du tableau de résultats affiche la légende pour chaque configuration de paramètres. Vous pouvez pointer sur chaque point pour afficher les détails de l’estimation des ressources à ce stade.
Cliquez sur un point {nombre de qubits, runtime} du diagramme d’espace-temps pour afficher le diagramme d’espace et les données de rapport correspondantes.
Conditions préalables pour Jupyter Notebook dans VS Code
Un environnement Python avec Python et Pip installés.
La dernière version de Visual Studio Code ou ouvrez VS Code sur le web.
VS Code avec le kit de développement Azure Quantum, Python et les extensions Jupyter installées .
La dernière version d’Azure Quantum
qsharp
etqsharp-widgets
des packages.python -m pip install --upgrade qsharp qsharp-widgets
Conseil
Vous n’avez pas besoin d’un compte Azure pour exécuter l’estimateur de ressources local.
Créer l’algorithme quantique
Dans VS Code, sélectionnez Afficher > la palette de commandes, puis Créer : nouveau Jupyter Notebook.
En haut à droite, VS Code détecte et affiche la version de Python et l’environnement Python virtuel qui a été sélectionné pour le notebook. Si vous avez plusieurs environnements Python, vous devrez peut-être sélectionner un noyau à l’aide du sélecteur de noyau en haut à droite. Si aucun environnement n’a été détecté, consultez Notebooks Jupyter dans VS Code pour plus d’informations sur l’installation.
Dans la première cellule du notebook, importez le
qsharp
package.import qsharp
Ajoutez une nouvelle cellule et copiez le code suivant.
%%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; }
Estimer l’algorithme quantique
À présent, vous estimez les ressources physiques de l’opération à l’aide RunProgram
des hypothèses par défaut. Ajoutez une nouvelle cellule et copiez le code suivant.
result = qsharp.estimate("RunProgram()")
result
La qsharp.estimate
fonction crée un objet de résultat, qui peut être utilisé pour afficher une table avec le nombre global de ressources physiques. Vous pouvez examiner les détails des coûts en réduisant les groupes, qui ont plus d’informations. Pour plus d’informations, consultez les données de rapport complètes de l’estimateur de ressources.
Par exemple, réduisez le groupe de paramètres de qubit logique pour voir que la distance du code est de 21 et que le nombre de qubits physiques est de 882.
Paramètre qubit logique | Valeur |
---|---|
Schéma QEC | surface_code |
Distance du code | 21 |
Qubits physiques | 882 |
Durée du cycle logique | 8 milisecs |
Taux d’erreur de qubit logique | 3.00E-13 |
Préfacteur de croisement | 0,03 |
Seuil de correction d’erreur | 0,01 |
Formule de temps de cycle logique | (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime ) * codeDistance |
Formule de qubits physiques | 2 * codeDistance * codeDistance |
Conseil
Pour une version plus compacte de la table de sortie, vous pouvez utiliser result.summary
.
Diagramme d’espace
La distribution des qubits physiques utilisés pour l’algorithme et les fabriques T est un facteur qui peut avoir un impact sur la conception de votre algorithme. Vous pouvez utiliser le qsharp-widgets
package pour visualiser cette distribution afin de mieux comprendre les besoins en espace estimé pour l’algorithme.
from qsharp_widgets import SpaceChart, EstimateDetails
SpaceChart(result)
Dans cet exemple, le nombre de qubits physiques requis pour exécuter l’algorithme est 829766, 196686 sont des qubits d’algorithme et 633080 dont des qubits de fabrique T.
Modifier les valeurs par défaut et estimer l’algorithme
Lorsque vous envoyez une demande d’estimation des ressources pour votre programme, vous pouvez spécifier des paramètres facultatifs. Utilisez le jobParams
champ pour accéder à tous les target paramètres qui peuvent être passés à l’exécution du travail et voir quelles valeurs par défaut ont été supposées :
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'}}
Vous pouvez voir que l’estimateur de ressources prend le qubit_gate_ns_e3
modèle de qubit, le code de correction d’erreur et le surface_code
budget d’erreur 0,001 comme valeurs par défaut pour l’estimation.
Voici les target paramètres qui peuvent être personnalisés :
errorBudget
- le budget d’erreur global autorisé pour l’algorithmeqecScheme
- le schéma de correction d’erreur quantique (QEC)qubitParams
- les paramètres de qubit physiqueconstraints
: contraintes au niveau du composantdistillationUnitSpecifications
- spécifications pour les algorithmes de distillation des usines TestimateType
- unique ou frontière
Pour plus d’informations, consultez Paramètres cibles pour l’estimateur de ressources.
Modifier le modèle de qubit
Vous pouvez estimer le coût du même algorithme à l’aide du paramètre qubit basé sur Majorana, qubitParams
, « qubit_maj_ns_e6 ».
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
}})
EstimateDetails(result_maj)
Modifier le schéma de correction des erreurs quantiques
Vous pouvez réexécuter le travail d’estimation des ressources pour le même exemple sur les paramètres de qubit basés sur Majorana avec un schéma QEC floqued, qecScheme
.
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
},
"qecScheme": {
"name": "floquet_code"
}})
EstimateDetails(result_maj)
Modifier le budget d’erreur
Ensuite, réexécutez le même circuit quantique avec un errorBudget
de 10 %.
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
},
"qecScheme": {
"name": "floquet_code"
},
"errorBudget": 0.1})
EstimateDetails(result_maj)
Traitement par lots avec l’estimateur de ressources
L’estimateur de ressources Azure Quantum vous permet d’exécuter plusieurs configurations de paramètres et de target comparer les résultats. Cela est utile lorsque vous souhaitez comparer le coût de différents modèles de qubit, schémas QEC ou budgets d’erreur.
Vous pouvez effectuer une estimation par lot en passant une liste de target paramètres au
params
paramètre de laqsharp.estimate
fonction . Par exemple, exécutez le même algorithme avec les paramètres par défaut et les paramètres de qubit basés sur Majorana avec un schéma 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⁻⁶"])
Modéliser Qubits logiques Profondeur logique États T Distance du code Fabriques T Fraction de fabrique T Qubits physiques rQOPS Temps d’exécution physique Basé sur une porte, ns, 10⁻³ 223 3,64 M 4,70 M 21 19 76.30 % 829.77k 26,55 M 31 secondes Majorana ns, 10⁻⁶ 223 3,64 M 4,70 M 5 19 63.02 % 79.60k 148,67 M 5 secondes Vous pouvez également construire une liste de paramètres d’estimation à l’aide de la
EstimatorParams
classe .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)
Modéliser Qubits logiques Profondeur logique États T Distance du code Fabriques T Fraction de fabrique T Qubits physiques rQOPS Temps d’exécution physique Basé sur une porte, µs, 10⁻³ 223 3,64 M 4,70 M 17 13 40.54 % 216.77k 21,86 Ko 10 heures Basé sur une porte, µs, 10⁻⁴ 223 3,64 M 4,70 M 9 14 43.17 % 63.57k 41.30k 5 heures Basé sur une porte, ns, 10⁻³ 223 3,64 M 4,70 M 17 16 69.08 % 416.89k 32,79 M 25 secondes Basé sur une porte, ns, 10⁻⁴ 223 3,64 M 4,70 M 9 14 43.17 % 63.57k 61,94 M 13 secondes Majorana ns, 10⁻⁴ 223 3,64 M 4,70 M 9 19 82.75 % 501.48k 82,59 M 10 secondes Majorana ns, 10⁻⁶ 223 3,64 M 4,70 M 5 13 31.47 % 42.96k 148,67 M 5 secondes
Exécution de l’estimation de la frontière pareto
Lors de l’estimation des ressources d’un algorithme, il est important de prendre en compte le compromis entre le nombre de qubits physiques et le runtime de l’algorithme. Vous pouvez envisager l’allocation d’autant de qubits physiques que possible pour réduire le runtime de l’algorithme. Toutefois, le nombre de qubits physiques est limité par le nombre de qubits physiques disponibles dans le matériel quantique.
L’estimation de la frontière de Pareto fournit plusieurs estimations pour le même algorithme, chacune avec un compromis entre le nombre de qubits et le runtime.
Pour exécuter l’estimateur de ressources à l’aide de l’estimation de la frontière pareto, vous devez spécifier le
"estimateType"
target paramètre en tant que"frontier"
. Par exemple, exécutez le même algorithme avec les paramètres de qubit basés sur Majorana avec un code de surface à l’aide de l’estimation de la frontière pareto.result = qsharp.estimate("RunProgram()", params= {"qubitParams": { "name": "qubit_maj_ns_e4" }, "qecScheme": { "name": "surface_code" }, "estimateType": "frontier", # frontier estimation } )
Vous pouvez utiliser la
EstimatesOverview
fonction pour afficher une table avec le nombre global de ressources physiques. Cliquez sur l’icône en regard de la première ligne pour sélectionner les colonnes que vous souhaitez afficher. Vous pouvez sélectionner un nom d’exécution, un type d’estimation, un type qubit, un schéma qec, un budget d’erreur, des qubits logiques, une profondeur logique, une distance de code, des états T, des fabriques T, une fraction de fabrique T, un runtime, des rQOPS et des qubits physiques.from qsharp_widgets import EstimatesOverview EstimatesOverview(result)
Dans la colonne Type d’estimation de la table de résultats, vous pouvez voir le nombre de combinaisons différentes de {nombre de qubits, runtime} pour votre algorithme. Dans ce cas, l’estimateur de ressources trouve 22 combinaisons optimales différentes parmi plusieurs milliers de combinaisons possibles.
Diagramme de l’espace-temps
La EstimatesOverview
fonction affiche également le diagramme de l’espace-temps de l’estimateur de ressources.
Le diagramme de l’espace-temps montre le nombre de qubits physiques et le runtime de l’algorithme pour chaque paire {nombre de qubits, runtime}. Vous pouvez pointer sur chaque point pour afficher les détails de l’estimation des ressources à ce stade.
Traitement par lot avec estimation de la frontière pareto
Pour estimer et comparer plusieurs configurations de target paramètres avec l’estimation de la frontière, ajoutez
"estimateType": "frontier",
aux paramètres.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"])
Notes
Vous pouvez définir des couleurs et des noms d’exécution pour le diagramme de qubit-temps à l’aide de la
EstimatesOverview
fonction .Lorsque vous exécutez plusieurs configurations de paramètres à l’aide de target l’estimation de la frontière Pareto, vous pouvez voir les estimations de ressources pour un point spécifique du diagramme espace-temps, c’est-à-dire pour chaque paire {nombre de qubits, runtime}. Par exemple, le code suivant montre l’utilisation des détails d’estimation pour la deuxième exécution (estimation de l’index=0) et la quatrième (point index=3) exécution la plus courte.
EstimateDetails(result[1], 4)
Vous pouvez également voir le diagramme d’espace pour un point spécifique du diagramme d’espace-temps. Par exemple, le code suivant montre le diagramme d’espace pour la première exécution de combinaisons (estimation index=0) et le troisième runtime le plus court (point index=2).
SpaceChart(result[0], 2)
Conditions préalables pour Qiskit
- Compte Azure avec un abonnement actif. Si vous n’avez pas de compte Azure, inscrivez-vous gratuitement et inscrivez-vous à un abonnement avec paiement à l’utilisation.
- Un espace de travail Azure Quantum. Pour plus d’informations, consultez Créer un espace de travail Azure Quantum.
Activer l’estimateur target de ressources Azure Quantum dans votre espace de travail
L’estimateur de ressources est un target fournisseur Microsoft Quantum Computing. Si vous avez créé un espace de travail depuis la publication de l’estimateur de ressources, le fournisseur Microsoft Quantum Computing a été ajouté automatiquement à votre espace de travail.
Si vous utilisez un espace de travail Azure Quantum existant :
- Ouvrez votre espace de travail dans le portail Azure.
- Dans le panneau de gauche, sous Opérations, sélectionnez Fournisseurs.
- Sélectionnez + Ajouter un fournisseur.
- Sélectionnez + Ajouter pour Microsoft Quantum Computing.
- Sélectionnez Découvrir & Développer , puis Ajouter.
Créer un notebook dans votre espace de travail
- Connectez-vous au Portail Azure et sélectionnez votre espace de travail Quantum Azure.
- Sous Opérations, sélectionnez Notebooks
- Cliquez sur Mes blocs-notes, puis sur Ajouter un nouveau.
- Dans Type de noyau, sélectionnez IPython.
- Tapez un nom pour le fichier, puis cliquez sur Créer un fichier.
Quand votre nouveau notebook s’ouvre, il crée automatiquement le code de la première cellule, en fonction de vos informations d’abonnement et d’espace de travail.
from azure.quantum import Workspace
workspace = Workspace (
resource_id = "", # Your resource_id
location = "" # Your workspace location (for example, "westus")
)
Notes
Sauf indication contraire, vous devez exécuter chaque cellule dans l’ordre de création pour éviter les problèmes de compilation.
Cliquez sur l’icône triangulaire « lecture » à gauche de la cellule pour exécuter le code.
Charger les importations requises
Tout d’abord, vous devez importer des modules supplémentaires à partir d’azure-quantum et qiskit
.
Cliquez sur + Code pour ajouter une nouvelle cellule, puis ajoutez et exécutez le code suivant :
from azure.quantum.qiskit import AzureQuantumProvider
from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import RGQFTMultiplier
Se connecter au service Azure Quantum
Ensuite, créez un objet AzureQuantumProvider à l’aide de l’objet workspace
de la cellule précédente pour vous connecter à votre espace de travail Azure Quantum. Vous créez un instance principal et définissez l’estimateur de ressources comme votre target.
provider = AzureQuantumProvider(workspace)
backend = provider.get_backend('microsoft.estimator')
Créer l’algorithme quantique
Dans cet exemple, vous créez un circuit quantique pour un multiplicateur basé sur la construction présentée dans Ruiz-Perez et Garcia-Escartin (arXiv :1411.5949) qui utilise la transformation de Fourier quantique pour implémenter l’arithmétique.
Vous pouvez ajuster la taille du multiplicateur en modifiant la bitwidth
variable. La génération de circuit est encapsulée dans une fonction qui peut être appelée avec la bitwidth
valeur du multiplicateur. L’opération aura deux registres d’entrée, chacun de la taille du spécifié bitwidth
et un registre de sortie qui est deux fois la taille du spécifié bitwidth
. La fonction imprime également des nombres de ressources logiques pour le multiplicateur extrait directement du circuit quantique.
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
Notes
Vous pouvez envoyer des travaux d’estimation des ressources physiques pour les algorithmes qui n’ont pas d’état T, mais qui ont au moins une mesure.
Estimer l’algorithme quantique
Créez une instance de votre algorithme à l’aide de la create_algorithm
fonction . Vous pouvez ajuster la taille du multiplicateur en modifiant la bitwidth
variable.
bitwidth = 4
circ = create_algorithm(bitwidth)
Estimez les ressources physiques pour cette opération à l’aide des hypothèses par défaut. Vous pouvez envoyer le circuit au back-end de l’estimateur de ressources à l’aide de la run
méthode , puis exécuter job.result()
pour attendre que le travail se termine et retourner les résultats.
job = backend.run(circ)
result = job.result()
result
Cela crée une table qui affiche le nombre global de ressources physiques. Vous pouvez examiner les détails des coûts en réduisant les groupes, qui ont plus d’informations.
Conseil
Pour une version plus compacte de la table de sortie, vous pouvez utiliser result.summary
.
Par exemple, si vous réduisez le groupe de paramètres de qubit logique , vous pouvez voir plus facilement que la distance du code de correction d’erreur est de 15.
Paramètre qubit logique | Valeur |
---|---|
Schéma QEC | surface_code |
Distance du code | 15 |
Qubits physiques | 450 |
Durée du cycle logique | 6us |
Taux d’erreur de qubit logique | 3.00E-10 |
Préfacteur de croisement | 0,03 |
Seuil de correction d’erreur | 0,01 |
Formule de temps de cycle logique | (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime ) * codeDistance |
Formule de qubits physiques | 2 * codeDistance * codeDistance |
Dans le groupe Paramètres de qubit physiques , vous pouvez voir les propriétés physiques de qubit qui ont été supposées pour cette estimation. Par exemple, le temps nécessaire pour effectuer une mesure à qubit unique et une porte à qubit unique est supposé être respectivement de 100 ns et de 50 ns.
Conseil
Vous pouvez également accéder à la sortie de l’estimateur de ressources en tant que dictionnaire Python à l’aide de la méthode result.data().
Pour plus d’informations, consultez la liste complète des données de sortie pour l’estimateur de ressources.
Diagrammes d’espace
La distribution des qubits physiques utilisés pour l’algorithme et les fabriques T est un facteur qui peut avoir un impact sur la conception de votre algorithme. Vous pouvez visualiser cette distribution pour mieux comprendre les besoins en espace estimé pour l’algorithme.
result.diagram.space
Le diagramme d’espace montre la proportion de qubits d’algorithme et de qubits de fabrique T. Notez que le nombre de copies de la fabrique T, 28, contribue au nombre de qubits physiques pour les fabriques T comme $\text{T factories} \cdot \text{physical qubit per T factory}= 28 \cdot 18 000 = 504 000$.
Pour plus d’informations, consultez Estimation physique de la fabrique T.
Modifier les valeurs par défaut et estimer l’algorithme
Lorsque vous envoyez une demande d’estimation des ressources pour votre programme, vous pouvez spécifier des paramètres facultatifs. Utilisez le jobParams
champ pour accéder à toutes les valeurs qui peuvent être passées à l’exécution du travail et voir quelles valeurs par défaut ont été supposées :
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'}}
Voici les target paramètres qui peuvent être personnalisés :
errorBudget
- le budget d’erreur global autoriséqecScheme
- le schéma de correction d’erreur quantique (QEC)qubitParams
- les paramètres de qubit physiqueconstraints
: contraintes au niveau du composantdistillationUnitSpecifications
- spécifications pour les algorithmes de distillation des usines T
Pour plus d’informations, consultez Paramètres cibles pour l’estimateur de ressources.
Modifier le modèle de qubit
Ensuite, estimez le coût du même algorithme à l’aide du paramètre qubit basé sur Majorana qubit_maj_ns_e6
job = backend.run(circ,
qubitParams={
"name": "qubit_maj_ns_e6"
})
result = job.result()
result
Vous pouvez inspecter les nombres physiques par programmation. Par exemple, vous pouvez explorer des détails sur la fabrique T qui a été créée pour exécuter l’algorithme.
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]}
Notes
Par défaut, le runtime est affiché en nanosecondes.
Vous pouvez utiliser ces données pour produire des explications sur la façon dont les fabriques T produisent les états T requis.
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)
Modifier le schéma de correction des erreurs quantiques
À présent, réexécutez le travail d’estimation des ressources pour le même exemple sur les paramètres de qubit basés sur Majorana avec un schéma 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
Modifier le budget d’erreur
Réexécuter le même circuit quantique avec une errorBudget
valeur de 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
Notes
Si vous rencontrez un problème lors de l’utilisation de l’estimateur de ressources, case activée la page Résolution des problèmes ou contactez AzureQuantumInfo@microsoft.com.
Étapes suivantes
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour