Różne sposoby uruchamiania narzędzia do szacowania zasobów
Z tego artykułu dowiesz się, jak pracować z narzędziem do szacowania zasobów usługi Azure Quantum. Narzędzie do szacowania zasobów jest dostępne zarówno w programie VS Code, jak i w trybie online w Azure Portal.
W poniższej tabeli przedstawiono różne sposoby uruchamiania narzędzia do szacowania zasobów.
Scenariusz użytkownika | Platforma | Samouczek |
---|---|---|
Szacowanie zasobów programu w języku Q# | Visual Studio Code | Wybierz pozycję Q# w programie VS Code w górnej części strony |
Szacowanie zasobów programu w języku Q# (zaawansowane) | Jupyter Notebook w usłudze Visual Studio Code | Wybierz pozycję Q# w Jupyter Notebook w górnej części strony |
Szacowanie zasobów programu Qiskit | Azure Quantum Portal | Wybierz pozycję Qiskit w Azure Portal w górnej części strony |
Szacowanie zasobów programu QIR | Azure Quantum Portal | Przesyłanie QIR |
Użyj plików FCIDUMP jako parametrów argumentu (zaawansowane) | Visual Studio Code | Przesyłanie problemu z chemią kwantową |
Uwaga
Zestaw Microsoft Quantum Development Kit (klasyczny zestaw QDK) nie będzie już obsługiwany po 30 czerwca 2024 r. Jeśli jesteś istniejącym deweloperem zestawu QDK, zalecamy przejście do nowego zestawu Azure Quantum Development Kit (Modern QDK), aby kontynuować opracowywanie rozwiązań kwantowych. Aby uzyskać więcej informacji, zobacz Migrowanie kodu Q# do nowoczesnego zestawu QDK.
Wymagania wstępne dotyczące programu VS Code
- Najnowsza wersja Visual Studio Code lub otwórz program VS Code w sieci Web.
- Najnowsza wersja rozszerzenia Azure Quantum Development Kit . Aby uzyskać szczegółowe informacje na temat instalacji, zobacz Instalowanie nowoczesnego zestawu QDK w programie VS Code.
Porada
Nie musisz mieć konta platformy Azure do uruchamiania lokalnego narzędzia do szacowania zasobów.
Twórca nowy plik języka Q#
- Otwórz Visual Studio Code i wybierz pozycję Plik > nowy plik tekstowy, aby utworzyć nowy plik.
- Zapisz plik jako
ShorRE.qs
. Ten plik będzie zawierać kod języka Q# dla programu.
Twórca algorytmu kwantowego
Skopiuj następujący kod do ShorRE.qs
pliku:
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;
}
}
Uruchamianie narzędzia do szacowania zasobów
Narzędzie do szacowania zasobów oferuje sześć wstępnie zdefiniowanych parametrów kubitu, z których cztery mają zestawy instrukcji opartych na bramie i dwa z zestawem instrukcji Majorana. Oferuje również dwa kody korekcyjne błędów kwantowych i surface_code
floquet_code
.
W tym przykładzie uruchomisz narzędzie do szacowania zasobów przy użyciu parametru kubitu qubit_gate_us_e3
i kodu korekty błędu kwantowego surface_code
.
Wybierz pozycję Widok —> Paleta poleceń i wpisz "resource", który powinien wyświetlić opcję Q#: Calculate Resource Estimates (Oblicz szacowanie zasobów ). Możesz również kliknąć pozycję Estimate (Szacowanie ) z listy poleceń poniżej
@EntryPoint()
. Wybierz tę opcję, aby otworzyć okno Narzędzia do szacowania zasobów.Aby oszacować zasoby, możesz wybrać co najmniej jeden parametr kubitu + typy kodu korekty błędu . W tym przykładzie wybierz pozycję qubit_gate_us_e3 i kliknij przycisk OK.
Określ budżet błędu lub zaakceptuj wartość domyślną 0,001. W tym przykładzie pozostaw wartość domyślną i naciśnij klawisz Enter.
Naciśnij klawisz Enter , aby zaakceptować domyślną nazwę wyniku na podstawie nazwy pliku, w tym przypadku ShorRE.
Wyświetlanie wyników
Narzędzie do szacowania zasobów udostępnia wiele oszacowań dla tego samego algorytmu, z których każdy pokazuje kompromisy między liczbą kubitów a środowiskiem uruchomieniowym. Zrozumienie kompromisu między środowiskiem uruchomieniowym a skalowaniem systemu jest jednym z ważniejszych aspektów szacowania zasobów.
Wynik szacowania zasobów jest wyświetlany w oknie Szacowanie języka Q# .
Karta Wyniki zawiera podsumowanie szacowania zasobów. Kliknij ikonę obok pierwszego wiersza, aby wybrać kolumny, które chcesz wyświetlić. Możesz wybrać określoną nazwę przebiegu, typ oszacowania, typ kubitu, schemat qec, budżet błędów, kubity logiczne, głębokość logiczną, odległość kodu, stany T, fabryki T, ułamek fabryki T, środowisko uruchomieniowe, rQOPS i kubity fizyczne.
W kolumnie Estimate type (Szacowanie typu ) tabeli wyników można zobaczyć liczbę optymalnych kombinacji {liczba kubitów, środowisko uruchomieniowe} dla algorytmu. Te kombinacje można zobaczyć na diagramie czasu kosmicznego.
Diagram czasowy pokazuje kompromisy między liczbą fizycznych kubitów a środowiskiem uruchomieniowym algorytmu. W tym przypadku narzędzie do szacowania zasobów znajduje 13 różnych optymalnych kombinacji z wielu tysięcy możliwych. Możesz umieścić wskaźnik myszy na każdej {liczbie kubitów, środowisku uruchomieniowym}, aby wyświetlić szczegóły szacowania zasobów w tym momencie.
Aby uzyskać więcej informacji, zobacz Diagram czasu przestrzeni.
Uwaga
Musisz kliknąć jeden punkt diagramu czasu kosmicznego, czyli {liczba kubitów, parę środowiska uruchomieniowego}, aby wyświetlić diagram przestrzeni i szczegóły szacowania zasobów odpowiadające temu punktowi.
Na diagramie kosmicznym przedstawiono rozkład fizycznych kubitów używanych dla algorytmu i fabryk T odpowiadających parom {liczba kubitów, runtime}. Jeśli na przykład wybierzesz najbardziej lewy punkt na diagramie czasu przestrzeni, liczba fizycznych kubitów wymaganych do uruchomienia algorytmu jest 427726, 196686 z których są kubitami algorytmów i 231040, z których są kubitami fabryki T.
Na koniec na karcie Szacowanie zasobów zostanie wyświetlona pełna lista danych wyjściowych narzędzia do szacowania zasobów odpowiadająca parze {liczba kubitów, runtime} . Szczegóły kosztów można sprawdzić, zwijając grupy, które zawierają więcej informacji. Na przykład wybierz najbardziej lewy punkt na diagramie czasu przestrzeni i zwiń grupę Parametry kubitu logicznego .
Parametr kubitu logicznego Wartość Schemat QEC surface_code Odległość kodu 21 Kubity fizyczne 882 Czas cyklu logicznego 13 milisecs Szybkość błędów kubitu logicznego 3.00E-13 Refaktoryzacja przeprawy 0.03 Próg korekty błędu 0,01 Formuła czasu cyklu logicznego (4 * + twoQubitGateTime
2 *oneQubitMeasurementTime
) *codeDistance
Formuła kubitów fizycznych 2 * codeDistance
*codeDistance
Porada
Kliknij pozycję Pokaż szczegółowe wiersze , aby wyświetlić opis poszczególnych danych wyjściowych raportu.
Aby uzyskać więcej informacji, zobacz pełne dane raportu narzędzia do szacowania zasobów.
Zmienianie parametrów target
Koszt tego samego programu w języku Q# można oszacować przy użyciu innego typu kubitu, kodu korekty błędów i budżetu błędu. Otwórz okno Narzędzie do szacowania zasobów, wybierając pozycję Widok —> Paleta poleceń i wpisz Q#: Calculate Resource Estimates
.
Wybierz dowolną inną konfigurację, na przykład parametr kubitu opartego na majoranie, qubit_maj_ns_e6
. Zaakceptuj domyślną wartość budżetu błędu lub wprowadź nową, a następnie naciśnij klawisz Enter. Narzędzie do szacowania zasobów ponownie uruchamia szacowanie przy użyciu nowych target parametrów.
Aby uzyskać więcej informacji, zobacz Parametry docelowe narzędzia do szacowania zasobów.
Uruchamianie wielu konfiguracji parametrów
Narzędzie do szacowania zasobów usługi Azure Quantum może uruchamiać wiele konfiguracji parametrów target i porównywać wyniki szacowania zasobów.
Wybierz pozycję Widok —> Paleta poleceń lub naciśnij klawisze Ctrl+Shift+P i wpisz
Q#: Calculate Resource Estimates
.Wybierz qubit_gate_us_e3, qubit_gate_us_e4, qubit_maj_ns_e4 + floquet_code i qubit_maj_ns_e6 + floquet_code, a następnie kliknij przycisk OK.
Zaakceptuj domyślną wartość budżetu błędu 0.001 i naciśnij klawisz Enter.
Naciśnij klawisz Enter , aby zaakceptować plik wejściowy, w tym przypadku ShorRE.qs.
W przypadku wielu konfiguracji parametrów wyniki są wyświetlane w różnych wierszach na karcie Wyniki .
Diagram czasu przestrzeni przedstawia wyniki wszystkich konfiguracji parametrów. Pierwsza kolumna tabeli wyników zawiera legendę dla każdej konfiguracji parametrów. Możesz zatrzymać wskaźnik myszy na każdym punkcie, aby zobaczyć szczegóły szacowania zasobów w tym momencie.
Kliknij punkt {liczba kubitów, środowisko uruchomieniowe} diagramu czasu przestrzeni, aby wyświetlić odpowiedni diagram przestrzeni i dane raportu.
Wymagania wstępne dotyczące Jupyter Notebook w programie VS Code
Środowisko języka Python z zainstalowanym językiem Python i programem Pip .
Najnowsza wersja Visual Studio Code lub otwórz program VS Code w sieci Web.
Program VS Code z zainstalowanymi rozszerzeniami Azure Quantum Development Kit, Python i Jupyter .
Najnowsza wersja usługi Azure Quantum
qsharp
iqsharp-widgets
pakiety.python -m pip install --upgrade qsharp qsharp-widgets
Porada
Nie musisz mieć konta platformy Azure do uruchamiania lokalnego narzędzia do szacowania zasobów.
Twórca algorytm kwantowy
W programie VS Code wybierz pozycję Wyświetl > paletę poleceń i wybierz pozycję Twórca: Nowy Jupyter Notebook.
W prawym górnym rogu program VS Code wykryje i wyświetli wersję języka Python oraz wirtualne środowisko języka Python wybrane dla notesu. Jeśli masz wiele środowisk języka Python, może być konieczne wybranie jądra przy użyciu selektora jądra w prawym górnym rogu. Jeśli nie wykryto żadnego środowiska, zobacz Notesy Jupyter Notebook w programie VS Code , aby uzyskać informacje o instalacji.
W pierwszej komórce notesu zaimportuj
qsharp
pakiet.import qsharp
Dodaj nową komórkę i skopiuj następujący kod.
%%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; }
Szacowanie algorytmu kwantowego
Teraz szacujesz zasoby fizyczne dla RunProgram
operacji przy użyciu domyślnych założeń. Dodaj nową komórkę i skopiuj następujący kod.
result = qsharp.estimate("RunProgram()")
result
Funkcja qsharp.estimate
tworzy obiekt wynikowy, który może służyć do wyświetlania tabeli z ogólnymi liczbami zasobów fizycznych. Szczegóły kosztów można sprawdzić, zwijając grupy, które zawierają więcej informacji. Aby uzyskać więcej informacji, zobacz pełne dane raportu narzędzia do szacowania zasobów.
Na przykład zwiń grupę Parametrów kubitu logicznego , aby zobaczyć, że odległość kodu wynosi 21, a liczba kubitów fizycznych wynosi 882.
Parametr kubitu logicznego | Wartość |
---|---|
Schemat QEC | surface_code |
Odległość kodu | 21 |
Kubity fizyczne | 882 |
Czas cyklu logicznego | 8 milisek |
Szybkość błędów kubitu logicznego | 3.00E-13 |
Refaktor przeprawy | 0.03 |
Próg korekty błędu | 0,01 |
Formuła czasu cyklu logicznego | (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime ) * codeDistance |
Formuła kubitów fizycznych | 2 * codeDistance * codeDistance |
Porada
Aby uzyskać bardziej kompaktowa wersję tabeli wyjściowej, można użyć polecenia result.summary
.
Diagram spacji
Rozkład fizycznych kubitów używanych dla algorytmu i fabryk T jest czynnikiem, który może mieć wpływ na projektowanie algorytmu. Za pomocą qsharp-widgets
pakietu można wizualizować tę dystrybucję, aby lepiej zrozumieć szacowane wymagania dotyczące miejsca dla algorytmu.
from qsharp-widgets import SpaceChart, EstimateDetails
SpaceChart(result)
W tym przykładzie liczba fizycznych kubitów wymaganych do uruchomienia algorytmu jest 829766, z których 196686 są kubitami algorytmów i 633080, z których są kubitami fabrycznymi T.
Zmienianie wartości domyślnych i szacowanie algorytmu
Podczas przesyłania żądania oszacowania zasobów dla programu można określić niektóre parametry opcjonalne. jobParams
Użyj pola, aby uzyskać dostęp do wszystkich target parametrów, które można przekazać do wykonania zadania i sprawdzić, które wartości domyślne zostały przyjęte:
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'}}
Widać, że narzędzie do szacowania zasobów przyjmuje qubit_gate_ns_e3
model kubitu, surface_code
kod korekty błędów i budżet błędu 0,001 jako wartości domyślne szacowania.
Są to target parametry, które można dostosować:
errorBudget
- ogólny dozwolony budżet błędów dla algorytmuqecScheme
— schemat korekty błędu kwantowego (QEC)qubitParams
- parametry kubitu fizycznegoconstraints
- ograniczenia na poziomie składnikadistillationUnitSpecifications
- specyfikacje algorytmów destylowania fabryk TestimateType
- pojedyncza lub granica
Aby uzyskać więcej informacji, zobacz Parametry docelowe narzędzia do szacowania zasobów.
Zmienianie modelu kubitu
Koszt dla tego samego algorytmu można oszacować przy użyciu parametru kubitu opartego na majoranie , qubitParams
"qubit_maj_ns_e6".
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
}})
EstimateDetails(result_maj)
Zmienianie schematu korekty błędów kwantowych
Możesz ponownie uruchomić zadanie szacowania zasobów dla tego samego przykładu dla parametrów kubitu opartego na majoranie za pomocą schematu QEC floqued. qecScheme
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
},
"qecScheme": {
"name": "floquet_code"
}})
EstimateDetails(result_maj)
Zmiana budżetu błędu
Następnie uruchom ponownie ten sam obwód kwantowy o errorBudget
wartości 10%.
result_maj = qsharp.estimate("RunProgram()", params={
"qubitParams": {
"name": "qubit_maj_ns_e6"
},
"qecScheme": {
"name": "floquet_code"
},
"errorBudget": 0.1})
EstimateDetails(result_maj)
Przetwarzanie wsadowe za pomocą narzędzia do szacowania zasobów
Narzędzie do szacowania zasobów usługi Azure Quantum umożliwia uruchamianie wielu konfiguracji parametrów target i porównywanie wyników. Jest to przydatne, gdy chcesz porównać koszt różnych modeli kubitów, schematów QEC lub budżetów błędów.
Szacowanie wsadowe można wykonać, przekazując listę parametrów target do
params
parametruqsharp.estimate
funkcji. Na przykład uruchom ten sam algorytm z parametrami domyślnymi i parametrami kubitu opartymi na majorze z schematem 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⁻⁶"])
Model Kubity logiczne Głębokość logiczna Stany T Odległość kodu Fabryki T Ułamek fabryki T Kubity fizyczne rQOPS Środowisko uruchomieniowe fizyczne Ns oparte na bramie, 10⁻³ 223 3,64 mln 4,70 mln 21 19 76.30 % 829,77 tys. 26,55 mln 31 s Majorana ns, 10⁻⁶ 223 3,64 mln 4,70 mln 5 19 63.02 % 79,60 tys. 148,67 mln 5 s Można również utworzyć listę parametrów szacowania przy użyciu
EstimatorParams
klasy .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)
Model Kubity logiczne Głębokość logiczna Stany T Odległość kodu Fabryki T Ułamek fabryki T Kubity fizyczne rQOPS Środowisko uruchomieniowe fizyczne μs oparte na bramie, 10⁻³ 223 3,64 mln 4,70 mln 17 13 40.54 % 216,77 tys. 21,86 tys. 10 godzin μs oparte na bramie, 10⁻⁴ 223 3,64 mln 4,70 mln 9 14 43.17 % 63,57 tys. 41.30 tys. 5 godzin Ns oparte na bramie, 10⁻³ 223 3,64 mln 4,70 mln 17 16 69.08 % 416,89 tys. 32,79 mln 25 s Ns oparte na bramie, 10⁻⁴ 223 3,64 mln 4,70 mln 9 14 43.17 % 63,57 tys. 61,94 mln 13 s Majorana ns, 10⁻⁴ 223 3,64 mln 4,70 mln 9 19 82.75 % 501.48 tys. 82,59 mln 10 s Majorana ns, 10⁻⁶ 223 3,64 mln 4,70 mln 5 13 31.47 % 42,96 tys. 148,67 mln 5 s
Szacowanie granic Pareto
Podczas szacowania zasobów algorytmu należy wziąć pod uwagę kompromis między liczbą fizycznych kubitów a środowiskiem uruchomieniowym algorytmu. Można rozważyć alokację jak największej liczby kubitów fizycznych, aby zmniejszyć środowisko uruchomieniowe algorytmu. Jednak liczba kubitów fizycznych jest ograniczona przez liczbę fizycznych kubitów dostępnych na sprzęcie kwantowym.
Szacowanie granic Pareto zapewnia wiele szacunków dla tego samego algorytmu, z których każda ma kompromis między liczbą kubitów a środowiskiem uruchomieniowym.
Aby uruchomić narzędzie do szacowania zasobów przy użyciu szacowania granic Pareto, należy określić
"estimateType"
target parametr jako"frontier"
. Na przykład uruchom ten sam algorytm z parametrami kubitu opartymi na majoranie z kodem powierzchniowym przy użyciu szacowania granic Pareto.result = qsharp.estimate("RunProgram()", params= {"qubitParams": { "name": "qubit_maj_ns_e4" }, "qecScheme": { "name": "surface_code" }, "estimateType": "frontier", # frontier estimation } )
Za pomocą
EstimatesOverview
funkcji można wyświetlić tabelę z ogólnymi liczbami zasobów fizycznych. Kliknij ikonę obok pierwszego wiersza, aby wybrać kolumny, które chcesz wyświetlić. Możesz wybrać elementy z nazwy uruchomienia, typu szacowania, typu kubitu, schematu qec, budżetu błędu, kubitów logicznych, głębokości logicznej, odległości kodu, stanów T, fabryk T, ułamka fabryki T, czasu wykonywania, rQOPS i kubitów fizycznych.from qsharp_widgets import EstimatesOverview EstimatesOverview(result)
W kolumnie Szacowanie typu tabeli wyników można zobaczyć liczbę różnych kombinacji {liczba kubitów, środowisko uruchomieniowe} dla algorytmu. W tym przypadku narzędzie do szacowania zasobów znajduje 22 różne optymalne kombinacje z wielu tysięcy możliwych.
Diagram czasu przestrzeni
Funkcja EstimatesOverview
wyświetla również diagram czasowy narzędzia do szacowania zasobów.
Diagram czasu przestrzeni przedstawia liczbę fizycznych kubitów i środowisko uruchomieniowe algorytmu dla każdej pary {liczba kubitów, runtime}. Możesz umieścić wskaźnik myszy na każdym punkcie, aby zobaczyć szczegóły szacowania zasobów w tym momencie.
Dzielenie na partie przy użyciu szacowania granic Pareto
Aby oszacować i porównać wiele konfiguracji parametrów target z szacowaniem granic, dodaj
"estimateType": "frontier",
do parametrów.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"])
Uwaga
Za pomocą funkcji można definiować kolory i nazwy przebiegów dla diagramu czasu kubitu
EstimatesOverview
.Podczas uruchamiania wielu konfiguracji parametrów target przy użyciu szacowania granic Pareto można zobaczyć oszacowania zasobów dla określonego punktu diagramu czasu przestrzeni, czyli dla każdej pary {liczba kubitów, runtime}. Na przykład poniższy kod przedstawia szacowane użycie szczegółów dla drugiego uruchomienia (estimate index=0) i czwartego (point index=3) najkrótszego środowiska uruchomieniowego.
EstimateDetails(result[1], 4)
Można również zobaczyć diagram przestrzeni dla określonego punktu diagramu czasu przestrzeni. Na przykład poniższy kod przedstawia diagram przestrzeni dla pierwszego uruchomienia kombinacji (estimate index=0) i trzeciego najkrótszego środowiska uruchomieniowego (point index=2).
SpaceChart(result[0], 2)
Wymagania wstępne dotyczące zestawu Qiskit
- Konto platformy Azure z aktywną subskrypcją. Jeśli nie masz konta platformy Azure, zarejestruj się bezpłatnie i zarejestruj się w celu korzystania z subskrypcji z płatnością zgodnie z rzeczywistym użyciem.
- Obszar roboczy usługi Azure Quantum. Aby uzyskać więcej informacji, zobacz Twórca obszar roboczy usługi Azure Quantum.
Włączanie narzędzia do szacowania target zasobów usługi Azure Quantum w obszarze roboczym
Narzędzie do szacowania zasobów jest dostawcą target obliczeń kwantowych firmy Microsoft. Jeśli obszar roboczy został utworzony od czasu wydania narzędzia do szacowania zasobów, dostawca microsoft Quantum Computing został automatycznie dodany do obszaru roboczego.
Jeśli używasz istniejącego obszaru roboczego usługi Azure Quantum:
- Otwórz obszar roboczy w Azure Portal.
- Na panelu po lewej stronie w obszarze Operacje wybierz pozycję Dostawcy.
- Wybierz pozycję + Dodaj dostawcę.
- Wybierz pozycję + Dodaj dla usługi Microsoft Quantum Computing.
- Wybierz pozycję Learn & Programowanie i wybierz pozycję Dodaj.
Twórca nowy notes w obszarze roboczym
- Zaloguj się do Azure Portal i wybierz swój obszar roboczy usługi Azure Quantum.
- W obszarze Operacje wybierz pozycję Notesy
- Kliknij pozycję Moje notesy i kliknij pozycję Dodaj nowy
- W obszarze Typ jądra wybierz pozycję IPython.
- Wpisz nazwę pliku, a następnie kliknij przycisk Twórca pliku.
Po otwarciu nowego notesu automatycznie tworzy kod dla pierwszej komórki na podstawie informacji o subskrypcji i obszarze roboczym.
from azure.quantum import Workspace
workspace = Workspace (
resource_id = "", # Your resource_id
location = "" # Your workspace location (for example, "westus")
)
Uwaga
O ile nie określono inaczej, należy uruchomić każdą komórkę w kolejności tworzenia, aby uniknąć problemów z kompilacją.
Kliknij trójkątną ikonę "odtwórz" po lewej stronie komórki, aby uruchomić kod.
Ładowanie wymaganych importów
Najpierw należy zaimportować dodatkowe moduły z modułów azure-quantum i qiskit
.
Kliknij pozycję + Kod , aby dodać nową komórkę, a następnie dodaj i uruchom następujący kod:
from azure.quantum.qiskit import AzureQuantumProvider
from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import RGQFTMultiplier
Nawiązywanie połączenia z usługą Azure Quantum
Następnie utwórz obiekt AzureQuantumProvider przy użyciu workspace
obiektu z poprzedniej komórki w celu nawiązania połączenia z obszarem roboczym usługi Azure Quantum. Utworzysz wystąpienie zaplecza i ustawisz narzędzie do szacowania zasobów jako .target
provider = AzureQuantumProvider(workspace)
backend = provider.get_backend('microsoft.estimator')
Twórca algorytmu kwantowego
W tym przykładzie utworzysz obwód kwantowy dla mnożnika na podstawie konstrukcji przedstawionej w ruiz-Perez i Garcia-Escartin (arXiv:1411.5949), który używa przekształcenia Quantum Fourier do implementowania arytmetyki.
Rozmiar mnożnika można dostosować, zmieniając zmienną bitwidth
. Generowanie obwodu jest opakowane w funkcję, którą można wywołać przy użyciu bitwidth
wartości mnożnika. Operacja będzie zawierać dwa rejestry wejściowe, każdy rozmiar określonego bitwidth
rejestru i jeden rejestr wyjściowy, który jest dwa razy większy od określonego bitwidth
. Funkcja wyświetli również niektóre liczby zasobów logicznych dla mnożnika wyodrębnionego bezpośrednio z obwodu kwantowego.
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
Uwaga
Zadania szacowania zasobów fizycznych można przesyłać dla algorytmów, które nie mają stanów T, ale mają co najmniej jedną miarę.
Szacowanie algorytmu kwantowego
Twórca wystąpienie algorytmu create_algorithm
przy użyciu funkcji . Rozmiar mnożnika można dostosować, zmieniając zmienną bitwidth
.
bitwidth = 4
circ = create_algorithm(bitwidth)
Szacuj zasoby fizyczne dla tej operacji przy użyciu domyślnych założeń. Obwód można przesłać do zaplecza narzędzia do szacowania zasobów przy użyciu run
metody , a następnie uruchomić polecenie job.result()
, aby poczekać na ukończenie zadania i zwrócić wyniki.
job = backend.run(circ)
result = job.result()
result
Spowoduje to utworzenie tabeli przedstawiającej ogólną liczbę zasobów fizycznych. Szczegóły kosztów można sprawdzić, zwijając grupy, które zawierają więcej informacji.
Porada
Aby uzyskać bardziej kompaktową wersję tabeli wyjściowej, można użyć polecenia result.summary
.
Jeśli na przykład zwiniesz grupę Parametrów kubitu logicznego , możesz łatwiej zobaczyć, że odległość kodu korekty błędu wynosi 15.
Parametr kubitu logicznego | Wartość |
---|---|
Schemat QEC | surface_code |
Odległość kodu | 15 |
Kubity fizyczne | 450 |
Czas cyklu logicznego | 6us |
Szybkość błędów kubitu logicznego | 3.00E-10 |
Refaktoryzacja przeprawy | 0.03 |
Próg korekty błędu | 0,01 |
Formuła czasu cyklu logicznego | (4 * + twoQubitGateTime 2 * oneQubitMeasurementTime ) * codeDistance |
Formuła kubitów fizycznych | 2 * codeDistance * codeDistance |
W grupie Parametry kubitu fizycznego można zobaczyć fizyczne właściwości kubitu, które zostały przyjęte dla tego oszacowania. Na przykład czas wykonywania pomiaru pojedynczego kubitu i bramki z jednym kubitem przyjmuje się odpowiednio 100 ns i 50 ns.
Porada
Możesz również uzyskać dostęp do danych wyjściowych narzędzia do szacowania zasobów jako słownika języka Python przy użyciu metody result.data().
Aby uzyskać więcej informacji, zobacz pełną listę danych wyjściowych narzędzia do szacowania zasobów.
Diagramy przestrzeni
Rozkład fizycznych kubitów używanych dla algorytmu i fabryk T jest czynnikiem, który może mieć wpływ na projektowanie algorytmu. Możesz zwizualizować tę dystrybucję, aby lepiej zrozumieć szacowane wymagania dotyczące miejsca dla algorytmu.
result.diagram.space
Na diagramie kosmicznym przedstawiono proporcję kubitów algorytmu i kubitów fabrycznych T. Należy pamiętać, że liczba kopii fabrycznych T, 28, przyczynia się do liczby fizycznych kubitów fabryk T jako $\text{fabryk T} \cdot \text{fizyczny kubit na fabrykę T}= 28 \cdot 18,000 = 504,000$.
Aby uzyskać więcej informacji, zobacz Szacowanie fizyczne fabryki T.
Zmienianie wartości domyślnych i szacowanie algorytmu
Podczas przesyłania żądania szacowania zasobów dla programu można określić niektóre parametry opcjonalne. jobParams
Użyj pola , aby uzyskać dostęp do wszystkich wartości, które można przekazać do wykonania zadania i sprawdzić, które wartości domyślne zostały przyjęte:
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'}}
Są to target parametry, które można dostosować:
errorBudget
— ogólny dozwolony budżet błędówqecScheme
- schemat korekty błędów kwantowych (QEC)qubitParams
- parametry kubitu fizycznegoconstraints
- ograniczenia na poziomie składnikówdistillationUnitSpecifications
- specyfikacje algorytmów destylacji fabryk T
Aby uzyskać więcej informacji, zobacz Target parameters for the Resource Estimator ( Parametry docelowe dla narzędzia do szacowania zasobów).
Zmienianie modelu kubitu
Następnie szacuj koszt dla tego samego algorytmu przy użyciu parametru kubitu opartego na majoranie qubit_maj_ns_e6
job = backend.run(circ,
qubitParams={
"name": "qubit_maj_ns_e6"
})
result = job.result()
result
Można programowo sprawdzić liczby fizyczne. Możesz na przykład zapoznać się ze szczegółami fabryki T, która została utworzona w celu wykonania algorytmu.
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]}
Uwaga
Domyślnie środowisko uruchomieniowe jest wyświetlane w nanosekundach.
Te dane umożliwiają przedstawienie pewnych wyjaśnień dotyczących sposobu produkcji wymaganych stanów T przez fabryki T.
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)
Zmienianie schematu korekty błędów kwantowych
Teraz uruchom ponownie zadanie szacowania zasobów dla tego samego przykładu dla parametrów kubitu opartego na majoranie z floqued schematem QEC. qecScheme
job = backend.run(circ,
qubitParams={
"name": "qubit_maj_ns_e6"
},
qecScheme={
"name": "floquet_code"
})
result_maj_floquet = job.result()
result_maj_floquet
Zmienianie budżetu błędów
Uruchommy ponownie ten sam obwód kwantowy o errorBudget
wartości 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
Uwaga
Jeśli wystąpi jakikolwiek problem podczas pracy z narzędziem do szacowania zasobów, zapoznaj się ze stroną Rozwiązywanie problemów lub skontaktuj się z .AzureQuantumInfo@microsoft.com
Następne kroki
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla