Verschiedene Möglichkeiten zum Ausführen des Ressourcenschätzungssteuerelements
In diesem Artikel erfahren Sie, wie Sie mit dem Azure Quantum Resource Estimator arbeiten. Die Ressourcenschätzung ist sowohl in VS Code als auch online in Azure-Portal verfügbar.
In der folgenden Tabelle sind die verschiedenen Methoden zum Ausführen des Ressourcenschätzungssteuerelements aufgeführt.
Benutzerszenario | Plattform | Tutorial |
---|---|---|
Schätzen der Ressourcen eines Q#-Programms | Visual Studio Code | Wählen Sie in VS Code oben auf der Seite Q# aus. |
Schätzen der Ressourcen eines Q#-Programms (erweitert) | Jupyter Notebook in Visual Studio Code | Wählen Sie in Jupyter Notebook oben auf der Seite Q# aus. |
Schätzen der Ressourcen eines Qiskit-Programms | Azure Quantum-Portal | Wählen Sie qiskit in Azure-Portal oben auf der Seite aus. |
Schätzen der Ressourcen eines QIR-Programms | Azure Quantum-Portal | Qir übermitteln |
Verwenden von FCIDUMP-Dateien als Argumentparameter (erweitert) | Visual Studio Code | Übermitteln eines Quantenchemieproblems |
Hinweis
Das Microsoft Quantum Development Kit (Classic QDK) wird nach dem 30. Juni 2024 nicht mehr unterstützt. Wenn Sie bereits QDK-Entwickler sind, empfehlen wir Ihnen, auf das neue Azure Quantum Development Kit (Modern QDK) umzusteigen, um die Entwicklung von Quantenlösungen fortzusetzen. Weitere Informationen finden Sie unter Migrieren Ihres Q#-Codes zum modernen QDK.
Voraussetzungen für VS Code
- Die neueste Version von Visual Studio Code , oder öffnen Sie VS Code im Web.
- Die neueste Version der Azure Quantum Development Kit-Erweiterung . Installationsdetails finden Sie unter Installieren des modernen QDK in VS Code.
Tipp
Sie benötigen kein Azure-Konto, um die lokale Ressourcenschätzung auszuführen.
Create einer neuen Q#-Datei
- Öffnen Sie Visual Studio Code, und wählen Sie Datei > Neue Textdatei aus, um eine neue Datei zu erstellen.
- Speichern Sie die Datei unter dem Namen
ShorRE.qs
. Diese Datei enthält den Q#-Code für Ihr Programm.
Create des Quantenalgorithmus
Kopieren Sie den folgenden Code in die Datei 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;
}
}
Ausführen des Ressourcenschätzungssteuerelements
Der Resource Estimator bietet sechs vordefinierte Qubitparameter, von denen vier über gatebasierte Befehlssätze und zwei über einen Majorana-Anweisungssatz verfügen. Außerdem werden zwei Quantenfehlerkorrekturcodessurface_code
und bereitgestelltfloquet_code
.
In diesem Beispiel führen Sie den Resource Estimator mit dem qubit_gate_us_e3
Qubit-Parameter und dem surface_code
Quantenfehlerkorrekturcode aus.
Wählen Sie Ansicht –> Befehlspalette aus, und geben Sie "Ressource" ein, um die Option Q#: Ressourcenschätzungen berechnen anzuzeigen. Sie können auch in der Liste der Befehle unter
@EntryPoint()
auf Schätzen klicken. Wählen Sie diese Option aus, um das Fenster Ressourcenschätzung zu öffnen.Sie können einen oder mehrere Qubit-Parameter + Fehlerkorrektur-Codetypen auswählen, für die die Ressourcen geschätzt werden sollen. Wählen Sie in diesem Beispiel qubit_gate_us_e3 aus, und klicken Sie auf OK.
Geben Sie das Fehlerbudget an , oder übernehmen Sie den Standardwert 0,001. Behalten Sie in diesem Beispiel den Standardwert bei, und drücken Sie die EINGABETASTE.
Drücken Sie die EINGABETASTE , um den Standardergebnisnamen basierend auf dem Dateinamen zu übernehmen, in diesem Fall ShorRE.
Anzeigen der Ergebnisse
Der Ressourcenschätzungsmodul stellt mehrere Schätzungen für denselben Algorithmus bereit, wobei jeweils Kompromisse zwischen der Anzahl der Qubits und der Laufzeit angezeigt werden. Das Verständnis des Kompromisses zwischen Laufzeit und Systemskalierung ist einer der wichtigsten Aspekte der Ressourcenschätzung.
Das Ergebnis der Ressourcenschätzung wird im Fenster Q#-Schätzung angezeigt.
Auf der Registerkarte Ergebnisse wird eine Zusammenfassung der Ressourcenschätzung angezeigt. Klicken Sie auf das Symbol neben der ersten Zeile, um die Anzuzeigenden Spalten auszuwählen. Sie können zwischen Ausführungsname, Schätzungstyp, Qubittyp, qec-Schema, Fehlerbudget, logischen Qubits, logischer Tiefe, Codeabstand, T-Zuständen, T-Factory-Zuständen, T-Factorybruch, Laufzeit, rQOPS und physischen Qubits auswählen.
In der Spalte Geschätzter Typ der Ergebnistabelle sehen Sie die Anzahl der optimalen Kombinationen von {Anzahl von Qubits, Runtime} für Ihren Algorithmus. Diese Kombinationen sind im Raum-Zeit-Diagramm zu sehen.
Das Raum-Zeit-Diagramm zeigt die Kompromisse zwischen der Anzahl der physischen Qubits und der Laufzeit des Algorithmus. In diesem Fall findet der Resource Estimator 13 verschiedene optimale Kombinationen von vielen Tausend möglichen Kombinationen. Sie können mit dem Mauszeiger auf jeden {Anzahl von Qubits, Runtime}-Punkt zeigen, um die Details der Ressourcenschätzung an diesem Punkt anzuzeigen.
Weitere Informationen finden Sie unter Raum-Zeit-Diagramm.
Hinweis
Sie müssen auf einen Punkt des Raum-Zeit-Diagramms klicken, d. h. auf ein {Anzahl von Qubits, Runtime}-Paar, um das Raumdiagramm und die Details der entsprechenden Ressourcenschätzung anzuzeigen.
Das Raumdiagramm zeigt die Verteilung der physischen Qubits, die für den Algorithmus und die T-Fabriken verwendet werden, entsprechend einem {Anzahl von Qubits, Runtime}-Paar. Wenn Sie beispielsweise den äußerst linken Punkt im Raum-Zeit-Diagramm auswählen, ist die Anzahl der physischen Qubits, die zum Ausführen des Algorithmus erforderlich sind, 427726, 196686 davon Algorithmus-Qubits und 231040 davon T-Factory-Qubits.
Schließlich wird auf der Registerkarte Ressourcenschätzungen die vollständige Liste der Ausgabedaten für die Ressourcenschätzung angezeigt, die einem {Anzahl von Qubits, Runtime}- Paar entspricht. Sie können die Kostendetails einsehen, indem Sie die Gruppen, die mehr Informationen enthalten, zuklappen. Wählen Sie beispielsweise den äußersten linken Punkt im Raum-Zeit-Diagramm aus, und reduzieren Sie die Gruppe Logische Qubitparameter .
Logischer Qubitparameter Wert QEC-Schema surface_code Codeabstand 21 Physische Qubits 882 Logische Zykluszeit 13 Mio. Fehlerrate logischer Qubits 3.00E-13 Überqueren des Präfaktors 0,03 Fehlerkorrekturschwellenwert 0.01 Formel für logische Zykluszeit (4 * twoQubitGateTime
+ 2 *oneQubitMeasurementTime
) *codeDistance
Formel für physische Qubits 2 * codeDistance
*codeDistance
Tipp
Klicken Sie auf Detaillierte Zeilen anzeigen , um die Beschreibung der einzelnen Ausgaben der Berichtsdaten anzuzeigen.
Weitere Informationen finden Sie in den vollständigen Berichtsdaten des Ressourcenschätzungssteuerelements.
Ändern der target Parameter
Sie können die Kosten für dasselbe Q#-Programm mit anderen Qubittypen, Fehlerkorrekturcode und Fehlerbudget schätzen. Öffnen Sie das Fenster Ressourcenschätzung, indem Sie Ansicht –> Befehlspalette auswählen, und geben Sie ein Q#: Calculate Resource Estimates
.
Wählen Sie eine beliebige andere Konfiguration aus, z. B. den Majorana-basierten Qubitparameter qubit_maj_ns_e6
. Übernehmen Sie den Standardfehlerbudgetwert, oder geben Sie einen neuen Fehler ein, und drücken Sie die EINGABETASTE. Der Ressourcenschätzungs-Wert wird mit den neuen target Parametern erneut ausgeführt.
Weitere Informationen finden Sie unter Zielparameter für die Ressourcenschätzung.
Ausführen mehrerer Konfigurationen von Parametern
Der Azure Quantum Resource Estimator kann mehrere Konfigurationen von target Parametern ausführen und die Ergebnisse der Ressourcenschätzung vergleichen.
Wählen Sie Ansicht –> Befehlspalette aus, oder drücken Sie STRG+UMSCHALT+P, und geben Sie ein
Q#: Calculate Resource Estimates
.Wählen Sie qubit_gate_us_e3, qubit_gate_us_e4, qubit_maj_ns_e4 + floquet_code und qubit_maj_ns_e6 + floquet_code aus, und klicken Sie auf OK.
Übernehmen Sie den Standardfehlerbudgetwert 0,001, und drücken Sie die EINGABETASTE.
Drücken Sie die EINGABETASTE , um die Eingabedatei zu akzeptieren, in diesem Fall ShorRE.qs.
Bei mehreren Konfigurationen von Parametern werden die Ergebnisse in verschiedenen Zeilen auf der Registerkarte Ergebnisse angezeigt.
Das Raum-Zeit-Diagramm zeigt die Ergebnisse für alle Konfigurationen von Parametern. In der ersten Spalte der Ergebnistabelle wird die Legende für jede Konfiguration von Parametern angezeigt. Sie können mit der Maus auf jeden Punkt zeigen, um die Details der Ressourcenschätzung an diesem Punkt anzuzeigen.
Klicken Sie auf einen {number of qubits, runtime}-Punkt des Raum-Zeit-Diagramms, um das entsprechende Raumdiagramm und die Berichtsdaten anzuzeigen.
Voraussetzungen für Jupyter Notebook in VS Code
Eine Python-Umgebung, in der Python und Pip installiert sind.
Die neueste Version von Visual Studio Code , oder öffnen Sie VS Code im Web.
VS Code mit installierten Erweiterungen Azure Quantum Development Kit, Python und Jupyter .
Die neuesten Azure Quantum
qsharp
- undqsharp-widgets
-Pakete.python -m pip install --upgrade qsharp qsharp-widgets
Tipp
Sie benötigen kein Azure-Konto, um die lokale Ressourcenschätzung auszuführen.
Create des Quantenalgorithmus
Wählen Sie in VS Code Befehlspalette anzeigen > und dann Create: Neue Jupyter Notebook aus.
Oben rechts erkennt VS Code die Version von Python und die virtuelle Python-Umgebung, die für das Notebook ausgewählt wurde, und zeigt sie an. Wenn Sie über mehrere Python-Umgebungen verfügen, müssen Sie möglicherweise einen Kernel mithilfe der Kernelauswahl oben rechts auswählen. Wenn keine Umgebung erkannt wurde, finden Sie unter Jupyter Notebooks in VS Code Setupinformationen.
Importieren Sie das
qsharp
Paket in der ersten Zelle des Notebooks.import qsharp
Fügen Sie eine neue Zelle hinzu, und kopieren Sie den folgenden Code.
%%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; }
Schätzen des Quantenalgorithmus
Nun schätzen Sie die physischen Ressourcen für den RunProgram
Vorgang mithilfe der Standardannahmen. Fügen Sie eine neue Zelle hinzu, und kopieren Sie den folgenden Code.
result = qsharp.estimate("RunProgram()")
result
Die qsharp.estimate
Funktion erstellt ein Ergebnisobjekt, das verwendet werden kann, um eine Tabelle mit der Gesamtzahl der physischen Ressourcen anzuzeigen. Sie können die Kostendetails einsehen, indem Sie die Gruppen, die mehr Informationen enthalten, zuklappen. Weitere Informationen finden Sie in den vollständigen Berichtsdaten des Ressourcenschätzungssteuerelements.
Reduzieren Sie beispielsweise die Gruppe logische Qubitparameter , um zu sehen, dass der Codeabstand 21 und die Anzahl der physischen Qubits 882 beträgt.
Logischer Qubitparameter | Wert |
---|---|
QEC-Schema | surface_code |
Codeabstand | 21 |
Physische Qubits | 882 |
Logische Zykluszeit | 8 Mio. |
Fehlerrate logischer Qubits | 3.00E-13 |
Überqueren des Präfaktors | 0,03 |
Fehlerkorrekturschwellenwert | 0.01 |
Formel für logische Zykluszeit | (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime ) * codeDistance |
Formel für physische Qubits | 2 * codeDistance * codeDistance |
Tipp
Für eine kompaktere Version der Ausgabetabelle können Sie verwenden result.summary
.
Raumdiagramm
Die Verteilung der physischen Qubits, die für den Algorithmus und die T-Fabriken verwendet werden, ist ein Faktor, der sich auf den Entwurf Ihres Algorithmus auswirken kann. Sie können das qsharp-widgets
Paket verwenden, um diese Verteilung zu visualisieren, um die geschätzten Speicherplatzanforderungen für den Algorithmus besser zu verstehen.
from qsharp-widgets import SpaceChart, EstimateDetails
SpaceChart(result)
In diesem Beispiel ist die Anzahl der physischen Qubits, die zum Ausführen des Algorithmus erforderlich sind, 829766, 196686 davon Algorithmus-Qubits und 633080 davon T-Factory-Qubits.
Ändern der Standardwerte und Schätzen des Algorithmus
Wenn Sie eine Ressourcenschätzungsanforderung für Ihr Programm übermitteln, können Sie einige optionale Parameter angeben. Verwenden Sie das jobParams
Feld, um auf alle Parameter zuzugreifen, die target an die Auftragsausführung übergeben werden können, und sehen Sie, welche Standardwerte angenommen wurden:
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'}}
Sie können sehen, dass die Ressourcenschätzung das qubit_gate_ns_e3
Qubitmodell, den surface_code
Fehlerkorrekturcode und das Fehlerbudget 0,001 als Standardwerte für die Schätzung verwendet.
Dies sind die Parameter, die target angepasst werden können:
errorBudget
– das insgesamt zulässige Fehlerbudget für den AlgorithmusqecScheme
– das QEC-Schema (Quantum Error Correction, Quantenfehlerkorrektur)qubitParams
– die physischen Qubitparameterconstraints
– die Einschränkungen auf KomponentenebenedistillationUnitSpecifications
- die Spezifikationen für T-Factory-DestillationsalgorithmenestimateType
- single oder frontier
Weitere Informationen finden Sie unter Zielparameter für die Ressourcenschätzung.
Ändern des Qubitmodells
Sie können die Kosten für denselben Algorithmus mithilfe des Majorana-basierten Qubitparameters qubitParams
, "qubit_maj_ns_e6" schätzen.
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
}})
EstimateDetails(result_maj)
Ändern des Quantenfehlerkorrekturschemas
Sie können den Auftrag für die Ressourcenschätzung für dasselbe Beispiel für die Majorana-basierten Qubitparameter mit einem floqueden QEC-Schema ( qecScheme
) erneut ausführen.
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
},
"qecScheme": {
"name": "floquet_code"
}})
EstimateDetails(result_maj)
Ändern des Fehlerbudgets
Führen Sie als Nächstes die gleiche Quantenschaltung mit einem errorBudget
Wert von 10 % erneut aus.
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
},
"qecScheme": {
"name": "floquet_code"
},
"errorBudget": 0.1})
EstimateDetails(result_maj)
Batchverarbeitung mit dem Resource Estimator
Mit dem Azure Quantum Resource Estimator können Sie mehrere Konfigurationen von target Parametern ausführen und die Ergebnisse vergleichen. Dies ist nützlich, wenn Sie die Kosten verschiedener Qubitmodelle, QEC-Schemas oder Fehlerbudgets vergleichen möchten.
Sie können eine Batchschätzung durchführen, indem Sie eine Liste von target Parametern an den
params
Parameter derqsharp.estimate
Funktion übergeben. Führen Sie beispielsweise den gleichen Algorithmus mit den Standardparametern und den Majorana-basierten Qubitparametern mit einem floqueden QEC-Schema aus.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⁻⁶"])
Modell Logische Qubits Logische Tiefe T-Zustände Codeabstand T-Factorys T-Factoryanteil Physische Qubits rQOPS Physische Ausführungszeit Gatterbasiert ns, 10⁻³ 223 3.64M 4,70 M 21 19 76.30 % 829,77 Kb 26,55 M 31 Sekunden Majorana ns, 10⁻⁶ 223 3.64M 4,70 M 5 19 63.02 % 79,60 k 148,67M 5 Sekunden Sie können auch eine Liste von Schätzungsparametern mithilfe der
EstimatorParams
-Klasse erstellen.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)
Modell Logische Qubits Logische Tiefe T-Zustände Codeabstand T-Factorys T-Factoryanteil Physische Qubits rQOPS Physische Ausführungszeit Gatterbasiert µs, 10⁻³ 223 3,64 M 4,70 M 17 13 40.54 % 216,77 Kb 21,86 Kb 10 Stunden Gatterbasiert µs, 10⁻⁴ 223 3.64M 4,70 M 9 14 43.17 % 63,57 Kb 41,30 k 5 Stunden Gatterbasiert ns, 10⁻³ 223 3,64 M 4,70 M 17 16 69.08 % 416,89 Kb 32,79 M 25 Sekunden Gatterbasiert ns, 10⁻⁴ 223 3,64 M 4,70 M 9 14 43.17 % 63,57 Kb 61,94M 13 Sekunden Majorana ns, 10⁻⁴ 223 3,64 M 4,70 M 9 19 82.75 % 501,48k 82,59M 10 Sekunden Majorana ns, 10⁻⁶ 223 3,64 M 4,70 M 5 13 31.47 % 42,96 Kb 148,67M 5 Sekunden
Ausführen einer Pareto-Grenzschätzung
Beim Schätzen der Ressourcen eines Algorithmus ist es wichtig, den Kompromiss zwischen der Anzahl der physischen Qubits und der Laufzeit des Algorithmus zu berücksichtigen. Sie könnten die Zuordnung von so vielen physischen Qubits wie möglich in Betracht ziehen, um die Laufzeit des Algorithmus zu reduzieren. Die Anzahl der physischen Qubits wird jedoch durch die Anzahl der physischen Qubits begrenzt, die in der Quantenhardware verfügbar sind.
Die Pareto-Grenzschätzung bietet mehrere Schätzungen für denselben Algorithmus mit jeweils einem Kompromiss zwischen der Anzahl der Qubits und der Laufzeit.
Um den Resource Estimator mithilfe der Pareto-Grenzschätzung auszuführen, müssen Sie den
"estimateType"
target Parameter als"frontier"
angeben. Führen Sie beispielsweise den gleichen Algorithmus mit den Majorana-basierten Qubitparametern mit einem Oberflächencode mithilfe der Pareto-Grenzschätzung aus.result = qsharp.estimate("RunProgram()", params= {"qubitParams": { "name": "qubit_maj_ns_e4" }, "qecScheme": { "name": "surface_code" }, "estimateType": "frontier", # frontier estimation } )
Sie können die
EstimatesOverview
Funktion verwenden, um eine Tabelle mit der Gesamtzahl der physischen Ressourcen anzuzeigen. Klicken Sie auf das Symbol neben der ersten Zeile, um die anzuzeigenden Spalten auszuwählen. Sie können zwischen Ausführungsname, Schätzungstyp, Qubittyp, qec-Schema, Fehlerbudget, logischen Qubits, logischer Tiefe, Codeabstand, T-Zustände, T-Fabriken, T Factory-Fraktion, Runtime, rQOPS und physischen Qubits auswählen.from qsharp_widgets import EstimatesOverview EstimatesOverview(result)
In der Spalte Schätzungstyp der Ergebnistabelle sehen Sie die Anzahl der verschiedenen Kombinationen von {number of qubits, runtime} für Ihren Algorithmus. In diesem Fall findet der Resource Estimator 22 verschiedene optimale Kombinationen aus vielen Tausend möglichen.
Raum-Zeit-Diagramm
Die EstimatesOverview
Funktion zeigt auch das Raum-Zeit-Diagramm des Resource Estimators an.
Das Raumzeitdiagramm zeigt die Anzahl der physischen Qubits und die Laufzeit des Algorithmus für jedes {Anzahl von Qubits, Runtime}-Paar. Sie können mit dem Mauszeiger auf jeden Punkt zeigen, um die Details der Ressourcenschätzung an diesem Punkt anzuzeigen.
Batchverarbeitung mit Pareto-Grenzschätzung
Fügen
"estimateType": "frontier",
Sie die Parameter hinzu, um mehrere Konfigurationen von target Parametern mit der Grenzschätzung zu schätzen und zu vergleichen.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"])
Hinweis
Sie können Farben und Ausführungsnamen für das Qubit-Zeitdiagramm mithilfe der
EstimatesOverview
-Funktion definieren.Wenn Sie mehrere Konfigurationen von target Parametern mithilfe der Pareto-Grenzschätzung ausführen, können Sie die Ressourcenschätzungen für einen bestimmten Punkt des Raum-Zeit-Diagramms anzeigen, d. h. für jedes {Anzahl von Qubits, Runtime}-Paar. Der folgende Code zeigt z. B. die Nutzung der Schätzungsdetails für die zweite Ausführung (Schätzungsindex=0) und die vierte (Punktindex=3) kürzeste Laufzeit.
EstimateDetails(result[1], 4)
Sie können auch das Raumdiagramm für einen bestimmten Punkt des Raumzeitdiagramms anzeigen. Der folgende Code zeigt z. B. das Leerzeichendiagramm für die erste Ausführung von Kombinationen (estimate index=0) und die dritt kürzeste Laufzeit (Punktindex=2).
SpaceChart(result[0], 2)
Voraussetzungen für Qiskit
- Ein Azure-Konto mit einem aktiven Abonnement. Wenn Sie über kein Azure-Konto verfügen, registrieren Sie sich kostenlos, und registrieren Sie sich für ein Abonnement mit nutzungsbasierter Bezahlung.
- Azure Quantum-Arbeitsbereich Weitere Informationen finden Sie unter Erstellen eines Azure Quantum-Arbeitsbereichs.
Aktivieren des Azure Quantum Resource Estimators target in Ihrem Arbeitsbereich
Der Resource Estimator ist ein target Anbieter von Microsoft Quantum Computing. Wenn Sie seit der Veröffentlichung des Resource Estimators einen Arbeitsbereich erstellt haben, wurde der Microsoft Quantum Computing-Anbieter Ihrem Arbeitsbereich automatisch hinzugefügt.
Wenn Sie einen vorhandenen Azure Quantum-Arbeitsbereich verwenden:
- Öffnen Sie Ihren Arbeitsbereich im Azure-Portal.
- Wählen Sie im linken Bereich unter Vorgänge die Option Anbieter aus.
- Wählen Sie + Anbieter hinzufügen aus.
- Wählen Sie + Hinzufügen für Microsoft Quantum Computing aus.
- Wählen Sie Lernen & Entwickeln aus, und wählen Sie Hinzufügen aus.
Erstellen eines neuen Notebooks in Ihrem Arbeitsbereich
- Melden Sie sich beim Azure-Portal an, und wählen Sie Ihren Azure Quantum-Arbeitsbereich aus.
- Wählen Sie unter Vorgängedie Option Notebooks aus.
- Klicken Sie auf Meine Notizbücher, und klicken Sie auf Neu hinzufügen.
- Wählen Sie unter Kerneltyp die Option IPython aus.
- Geben Sie einen Namen für die Datei ein, und klicken Sie auf Create Datei.
Wenn Ihr neues Notebook geöffnet wird, wird der Code für die erste Zelle automatisch auf der Grundlage Ihrer Abonnement- und Arbeitsbereichsinformationen erstellt.
from azure.quantum import Workspace
workspace = Workspace (
resource_id = "", # Your resource_id
location = "" # Your workspace location (for example, "westus")
)
Hinweis
Sofern nicht anders angegeben, müssen Sie die einzelnen Zellen in der Reihenfolge ihrer Erstellung ausführen, um Kompilierungsprobleme zu vermeiden.
Klicken Sie links neben der Zelle auf das dreieckige Wiedergabesymbol, um den Code auszuführen.
Laden der erforderlichen Importe
Zunächst müssen Sie zusätzliche Module aus azure-quantum und qiskit
importieren.
Klicken Sie auf + Code, um eine neue Zelle hinzuzufügen, fügen Sie dann den folgenden Code hinzu, und führen Sie ihn aus:
from azure.quantum.qiskit import AzureQuantumProvider
from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import RGQFTMultiplier
Herstellen einer Verbindung mit dem Azure Quantum-Dienst
Erstellen Sie als Nächstes ein AzureQuantumProvider-Objekt , indem Sie das workspace
Objekt aus der vorherigen Zelle verwenden, um eine Verbindung mit Ihrem Azure Quantum-Arbeitsbereich herzustellen. Sie erstellen ein Back-End-instance und legen den Resource Estimator auf Ihr targetfest.
provider = AzureQuantumProvider(workspace)
backend = provider.get_backend('microsoft.estimator')
Create des Quantenalgorithmus
In diesem Beispiel erstellen Sie eine Quantenschaltung für einen Multiplikator basierend auf der in Ruiz-Perez und Garcia-Escartin dargestellten Konstruktion (arXiv:1411.5949), die die Quanten-Fourier-Transformation verwendet, um Arithmetik zu implementieren.
Sie können die Größe des Multiplikators anpassen, indem Sie die bitwidth
Variable ändern. Die Leitungsgenerierung wird in eine Funktion umschlossen, die mit dem bitwidth
Wert des Multiplikators aufgerufen werden kann. Der Vorgang verfügt über zwei Eingaberegister, jedes die Größe des angegebenen bitwidth
und ein Ausgaberegister, das doppelt so groß ist wie der angegebene bitwidth
. Die Funktion gibt auch einige logische Ressourcenanzahlen für den direkt aus der Quantenschaltung extrahierten Multiplikator aus.
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
Hinweis
Sie können Aufträge zur Schätzung physischer Ressourcen für Algorithmen übermitteln, die keine T-Zustände haben, aber mindestens eine Messung aufweisen.
Schätzen des Quantenalgorithmus
Create mithilfe create_algorithm
der Funktion einen instance Ihres Algorithmus. Sie können die Größe des Multiplikators anpassen, indem Sie die bitwidth
Variable ändern.
bitwidth = 4
circ = create_algorithm(bitwidth)
Schätzen Sie die physischen Ressourcen für diesen Vorgang mithilfe der Standardannahmen. Sie können die Verbindung mithilfe run
der -Methode an das Resource Estimator-Back-End übermitteln und dann ausführen job.result()
, um auf den Abschluss des Auftrags zu warten und die Ergebnisse zurückzugeben.
job = backend.run(circ)
result = job.result()
result
Dadurch wird eine Tabelle erstellt, in der die Gesamtzahl der physischen Ressourcen angezeigt wird. Sie können die Kostendetails einsehen, indem Sie die Gruppen, die mehr Informationen enthalten, zuklappen.
Tipp
Für eine kompaktere Version der Ausgabetabelle können Sie verwenden result.summary
.
Wenn Sie beispielsweise die Gruppe logische Qubitparameter reduzieren, können Sie leichter erkennen, dass der Fehlerkorrekturcodeabstand 15 beträgt.
Logischer Qubitparameter | Wert |
---|---|
QEC-Schema | surface_code |
Codeabstand | 15 |
Physische Qubits | 450 |
Logische Zykluszeit | 6us |
Logische Qubitfehlerrate | 3.00E-10 |
Kreuzen von Präfaktoren | 0,03 |
Fehlerkorrekturschwellenwert | 0.01 |
Formel der Logischen Zykluszeit | (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime ) * codeDistance |
Formel für physische Qubits | 2 * codeDistance * codeDistance |
In der Gruppe Physische Qubitparameter sehen Sie die physischen Qubiteigenschaften, die für diese Schätzung angenommen wurden. So beträgt beispielsweise die Zeit für die Durchführung der Messung eines einzelnen Qubits und eines einzelnen Qubitgatters 100 ns bzw. 50 ns.
Tipp
Sie können auch mit der result.data() -Methode als Python-Wörterbuch auf die Ausgabe des Resource Estimator zugreifen.
Weitere Informationen finden Sie in der vollständigen Liste der Ausgabedaten für den Resource Estimator.
Raumdiagramme
Die Verteilung der physischen Qubits, die für den Algorithmus und die T-Fabriken verwendet werden, ist ein Faktor, der sich auf das Design Ihres Algorithmus auswirken kann. Sie können diese Verteilung visualisieren, um den geschätzten Platzbedarf für den Algorithmus besser zu verstehen.
result.diagram.space
Das Raumdiagramm zeigt den Anteil von Algorithmusqubits und T Factory-Qubits. Beachten Sie, dass die Anzahl der T Factory-Kopien(28) zur Anzahl der physischen Qubits für T-Fabriken als $\text{T factories} \cdot \text{physical qubit per T factory}= 28 \cdot 18.000 = 504.000$ beiträgt.
Weitere Informationen finden Sie unter Physische T Factory-Schätzung.
Ändern der Standardwerte und Schätzen des Algorithmus
Wenn Sie eine Ressourcenschätzungsanforderung für Ihr Programm übermitteln, können Sie einige optionale Parameter angeben. Verwenden Sie das jobParams
Feld, um auf alle Werte zuzugreifen, die an die Auftragsausführung übergeben werden können, und sehen Sie, welche Standardwerte angenommen wurden:
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'}}
Dies sind die Parameter, die target angepasst werden können:
errorBudget
- Das zulässige Gesamtbudget für FehlerqecScheme
- das QEC-Schema (Quantum Error Correction, Quantenfehlerkorrektur)qubitParams
- die physischen Qubitparameterconstraints
– die Einschränkungen auf KomponentenebenedistillationUnitSpecifications
- die Spezifikationen für T-Fabriken-Destillationsalgorithmen
Weitere Informationen finden Sie unter Zielparameter für den Resource Estimator.
Ändern des Qubitmodells
Schätzen Sie als Nächstes die Kosten für denselben Algorithmus mithilfe des Majorana-basierten Qubitparameters. qubit_maj_ns_e6
job = backend.run(circ,
qubitParams={
"name": "qubit_maj_ns_e6"
})
result = job.result()
result
Sie können die physischen Anzahlen programmgesteuert überprüfen. Beispielsweise können Sie Details zur T-Factory untersuchen, die zum Ausführen des Algorithmus erstellt wurde.
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]}
Hinweis
Standardmäßig wird die Laufzeit in Nanosekunden angezeigt.
Sie können diese Daten verwenden, um einige Erklärungen zu erstellen, wie die T-Fabriken die erforderlichen T-Zustände erzeugen.
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)
Ändern des Quantenfehlerkorrekturschemas
Führen Sie nun den Ressourcenschätzungsauftrag für dasselbe Beispiel für die Majorana-basierten Qubitparameter mit einem floqueden QEC-Schema( qecScheme
erneut aus.
job = backend.run(circ,
qubitParams={
"name": "qubit_maj_ns_e6"
},
qecScheme={
"name": "floquet_code"
})
result_maj_floquet = job.result()
result_maj_floquet
Ändern des Fehlerbudgets
Führen Wir dieselbe Quantenschaltung mit einer errorBudget
von 10 % erneut aus.
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
Hinweis
Wenn beim Arbeiten mit dem Resource Estimator ein Problem aufgetreten ist, lesen Sie die Seite Problembehandlung, oder wenden Sie sich an AzureQuantumInfo@microsoft.com.
Nächste Schritte
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für