Dela via


Olika sätt att köra Resource Estimator

I den här artikeln lär du dig att arbeta med Azure Quantum Resource Estimator. Resursberäknaren är tillgänglig både i VS Code och online i Azure-portalen.

I följande tabell visas de olika sätten att köra Resource Estimator.

Användarscenario Plattform Självstudier
Beräkna resurserna för ett Q#-program Visual Studio-koden Välj Q# i VS Code överst på sidan
Beräkna resurserna för ett Q#-program (avancerat) Jupyter Notebook i Visual Studio Code Välj Q# i Jupyter Notebook överst på sidan
Beräkna resurserna för ett Qiskit-program Azure Quantum-portalen Välj Qiskit i Azure-portalen överst på sidan
Beräkna resurserna i ett QIR-program Azure Quantum-portalen Skicka QIR
Använda FCIDUMP-filer som argumentparametrar (avancerat) Visual Studio-koden Skicka in ett kvantkemiproblem

Kommentar

Microsoft Quantum Development Kit (klassisk QDK) stöds inte längre efter den 30 juni 2024. Om du är en befintlig QDK-utvecklare rekommenderar vi att du övergår till det nya Azure Quantum Development Kit (Modern QDK) för att fortsätta utveckla kvantlösningar. Mer information finns i Migrera Q#-koden till modern QDK.

Krav för VS Code

Dricks

Du behöver inte ha något Azure-konto för att köra den lokala resursberäknaren.

Skapa en ny Q#-fil

  1. Öppna Visual Studio Code och välj Fil > Ny textfil för att skapa en ny fil.
  2. Spara filen som ShorRE.qs. Den här filen innehåller Q#-koden för ditt program.

Skapa kvantalgoritmen

Kopiera följande kod till ShorRE.qs filen:

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 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 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;
    }
}

Kör resursberäknaren

Resource Estimator erbjuder sex fördefinierade qubitparametrar, varav fyra har gatebaserade instruktionsuppsättningar och två som har en Majorana-instruktionsuppsättning. Den erbjuder också två korrigeringskodersurface_code för kvantfel och floquet_code.

I det här exemplet kör du Resource Estimator med kvantbitsparametern qubit_gate_us_e3 och korrigeringskoden för surface_code kvantfel.

  1. Välj Visa –> kommandopalett och skriv "resurs" som ska ta upp alternativet Q#: Beräkna resursuppskattningar . Du kan också klicka på Uppskatta i listan med kommandon nedan @EntryPoint(). Välj det här alternativet om du vill öppna fönstret Resursberäknare.

    Skärmbild som visar hur du väljer uppskattningskommandot från kodobjektivlistan.

  2. Du kan välja en eller flera qubitparameter + felkorrigeringskodtyper att uppskatta resurserna för. I det här exemplet väljer du qubit_gate_us_e3 och klickar på OK.

    Skärmbild som visar hur du väljer kvantbitsparametern från resursuppskattningsmenyn.

  3. Ange felbudgeten eller acceptera standardvärdet 0.001. I det här exemplet lämnar du standardvärdet och trycker på Retur.

  4. Tryck på Retur för att acceptera standardresultatnamnet baserat på filnamnet, i det här fallet ShorRE.

Visa resultatet

Resource Estimator innehåller flera uppskattningar för samma algoritm, var och en visar kompromisser mellan antalet kvantbitar och körningen. Att förstå kompromissen mellan körning och systemskala är en av de viktigaste aspekterna av resursuppskattning.

Resultatet av resursuppskattningen visas i fönstret Q#-uppskattning .

  1. fliken Resultat visas en sammanfattning av resursuppskattningen. Klicka på ikonen bredvid den första raden för att välja de kolumner som du vill visa. Du kan välja mellan körningsnamn, uppskattningstyp, kvantbitstyp, qec-schema, felbudget, logiska kvantbitar, logiskt djup, kodavstånd, T-tillstånd, T-fabriker, T-fabriksfraktion, körning, rQOPS och fysiska kvantbitar.

    Skärmbild som visar hur du visar menyn för att välja de utdata för resursuppskattning som du väljer.

    I kolumnen Uppskattningstyp i resultattabellen kan du se antalet optimala kombinationer av {antal qubits, runtime} för din algoritm. Dessa kombinationer kan visas i diagrammet för rumstid.

  2. Diagrammet Space-time visar kompromisserna mellan antalet fysiska kvantbitar och algoritmens körning. I det här fallet hittar Resource Estimator 13 olika optimala kombinationer av många tusen möjliga kombinationer. Du kan hovra över varje {antal kvantbitar, runtime} punkt för att se information om resursuppskattningen vid den tidpunkten.

    Skärmbild som visar tidsdiagrammet för resursberäknaren.

    Mer information finns i Diagram över tidsrymd.

    Kommentar

    Du måste klicka på en punkt i tidsdiagrammet, dvs. ett {antal qubits, runtime}-par, för att se utrymmesdiagrammet och informationen om den resursuppskattning som motsvarar den punkten.

  3. Diagrammet Utrymme visar fördelningen av fysiska kvantbitar som används för algoritmen och T-fabrikerna, vilket motsvarar ett {antal qubits, runtime}-par. Om du till exempel väljer den vänstra punkten i tidsdiagrammet är antalet fysiska kvantbitar som krävs för att köra algoritmen 427726, 196686 som är algoritmkvabits och 231040 som är T-fabriks qubitar.

    Skärmbild som visar utrymmesdiagrammet för Resursberäknaren.

  4. Slutligen visar fliken Resursuppskattningar den fullständiga listan över utdata för resursberäknaren som motsvarar ett {antal qubits, runtime}-par. Du kan kontrollera kostnadsinformationen genom att komprimera grupperna, som har mer information. Välj till exempel den vänstra punkten i diagrammet för utrymmestid och dölj gruppen Logiska qubitparametrar .

    Logisk qubit-parameter Värde
    QEC-schema surface_code
    Kodavstånd 21
    Fysiska kvantbitar 882
    Logisk cykeltid 13 millisek
    Felfrekvens för logisk kvantbit 3.00E-13
    Korsande förfaktor 0.03
    Tröskelvärde för felkorrigering 0.01
    Formel för logisk cykeltid (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime) * codeDistance
    Formel för fysiska kvantbitar 2 * codeDistance * codeDistance

    Dricks

    Klicka på Visa detaljerade rader för att visa beskrivningen av varje utdata för rapportdata.

    Mer information finns i fullständiga rapportdata för Resource Estimator.

Ändra parametrarna target

Du kan beräkna kostnaden för samma Q#-program med hjälp av annan kvantbitstyp, felkorrigeringskod och felbudget. Öppna fönstret Resursberäknare genom att välja Visa –> kommandopalett och skriv Q#: Calculate Resource Estimates.

Välj valfri annan konfiguration, till exempel parametern Majorana-baserad qubit, qubit_maj_ns_e6. Acceptera standardvärdet för felbudget eller ange ett nytt och tryck på Retur. Resource Estimator kör uppskattningen igen med de nya target parametrarna.

Mer information finns i Målparametrar för resursberäknaren.

Köra flera konfigurationer av parametrar

Azure Quantum Resource Estimator kan köra flera konfigurationer av parametrar och jämföra resultatet av target resursuppskattningen.

  1. Välj Visa –> Kommandopalett eller tryck på Ctrl+Skift+P och skriv Q#: Calculate Resource Estimates.

  2. Välj qubit_gate_us_e3, qubit_gate_us_e4, qubit_maj_ns_e4 + floquet_code och qubit_maj_ns_e6 + floquet_code och klicka på OK.

  3. Acceptera standardfelets budgetvärde 0.001 och tryck på Retur.

  4. Tryck på Retur för att acceptera indatafilen, i det här fallet ShorRE.qs.

  5. När det gäller flera konfigurationer av parametrar visas resultatet i olika rader på fliken Resultat .

  6. Diagrammet Space-time visar resultatet för alla konfigurationer av parametrar. Den första kolumnen i resultattabellen visar förklaringen för varje konfiguration av parametrar. Du kan hovra över varje punkt för att se information om resursuppskattningen vid den tidpunkten.

    Skärmbild som visar tidsdiagrammet och resultattabellen när du kör flera konfigurationer av parametern i Resursberäknaren.

  7. Klicka på en {antal qubits, runtime} i tidsdiagrammet för att hämta motsvarande utrymmesdiagram och rapportdata.

Förutsättningar för Jupyter Notebook i VS Code

Dricks

Du behöver inte ha något Azure-konto för att köra den lokala resursberäknaren.

Skapa kvantalgoritmen

  1. I VS Code väljer du Visa > kommandopalett och väljer Skapa: Ny Jupyter Notebook.

  2. I det övre högra hörnet identifierar och visar VS Code den version av Python och den virtuella Python-miljön som har valts för notebook-filen. Om du har flera Python-miljöer kan du behöva välja en kernel med hjälp av kernelväljaren längst upp till höger. Om ingen miljö har identifierats kan du läsa mer i Jupyter Notebooks i VS Code .

  3. Importera paketet i den första cellen i notebook-filen qsharp .

    import qsharp
    
  4. Lägg till en ny cell och kopiera följande 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;
    }
    

Beräkna kvantalgoritmen

Nu beräknar du de fysiska resurserna för RunProgram åtgärden med hjälp av standardantagandena. Lägg till en ny cell och kopiera följande kod.

result = qsharp.estimate("RunProgram()")
result

Funktionen qsharp.estimate skapar ett resultatobjekt som kan användas för att visa en tabell med det totala antalet fysiska resurser. Du kan kontrollera kostnadsinformationen genom att komprimera grupperna, som har mer information. Mer information finns i fullständiga rapportdata för Resource Estimator.

Dölj till exempel gruppen Logiska qubitparametrar för att se att kodavståndet är 21 och att antalet fysiska kvantbitar är 882.

Logisk qubit-parameter Värde
QEC-schema surface_code
Kodavstånd 21
Fysiska kvantbitar 882
Logisk cykeltid 8 millisek
Felfrekvens för logisk kvantbit 3.00E-13
Korsande förfaktor 0.03
Tröskelvärde för felkorrigering 0.01
Formel för logisk cykeltid (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime) * codeDistance
Formel för fysiska kvantbitar 2 * codeDistance * codeDistance

Dricks

Om du vill ha en mer kompakt version av utdatatabellen kan du använda result.summary.

Blankstegsdiagram

Fördelningen av fysiska kvantbitar som används för algoritmen och T-fabrikerna är en faktor som kan påverka utformningen av algoritmen. Du kan använda qsharp-widgets paketet för att visualisera den här fördelningen för att bättre förstå de uppskattade utrymmeskraven för algoritmen.

from qsharp-widgets import SpaceChart, EstimateDetails
SpaceChart(result)

I det här exemplet är antalet fysiska kvantbitar som krävs för att köra algoritmen 829766, 196686 av vilka är algoritmens kvantbitar och 633080 som är T-fabriks qubitar.

Skärmbild som visar utrymmesdiagrammet för resursberäknaren.

Ändra standardvärdena och uppskatta algoritmen

När du skickar en resursuppskattningsbegäran för ditt program kan du ange några valfria parametrar. Använd fältet jobParams för att komma åt alla target parametrar som kan skickas till jobbkörningen och se vilka standardvärden som antogs:

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'}}

Du kan se att Resource Estimator tar qubit_gate_ns_e3 kvantbitsmodellen, felkorrigeringskoden surface_code och felbudgeten 0,001 som standardvärden för uppskattningen.

Det här är de target parametrar som kan anpassas:

  • errorBudget – den övergripande tillåtna felbudgeten för algoritmen
  • qecScheme – QEC-schemat (Quantum Error Correction)
  • qubitParams – de fysiska kvantbitsparametrarna
  • constraints – begränsningarna på komponentnivå
  • distillationUnitSpecifications - specifikationerna för algoritmer för destillation av T-fabriker
  • estimateType - enkel eller gräns

Mer information finns i Målparametrar för resursberäknaren.

Ändra qubitmodell

Du kan beräkna kostnaden för samma algoritm med hjälp av parametern Majorana-baserad qubit, qubitParams, "qubit_maj_ns_e6".

result_maj = qsharp.estimate("RunProgram()", params={
                "qubitParams": {
                    "name": "qubit_maj_ns_e6"
                }})
EstimateDetails(result_maj)

Ändra korrigeringsschema för kvantfel

Du kan köra resursuppskattningsjobbet igen för samma exempel på de Majorana-baserade qubitparametrarna med ett floqued QEC-schema, qecScheme.

result_maj = qsharp.estimate("RunProgram()", params={
                "qubitParams": {
                    "name": "qubit_maj_ns_e6"
                },
                "qecScheme": {
                    "name": "floquet_code"
                }})
EstimateDetails(result_maj)

Budget för ändringsfel

Kör sedan om samma kvantkrets med errorBudget 10 %.

result_maj = qsharp.estimate("RunProgram()", params={
                "qubitParams": {
                    "name": "qubit_maj_ns_e6"
                },
                "qecScheme": {
                    "name": "floquet_code"
                },
                "errorBudget": 0.1})
EstimateDetails(result_maj)

Batchbearbetning med resursberäknaren

Med Azure Quantum Resource Estimator kan du köra flera konfigurationer av target parametrar och jämföra resultaten. Detta är användbart när du vill jämföra kostnaden för olika qubit-modeller, QEC-scheman eller felbudgetar.

  1. Du kan utföra en batchuppskattning genom att skicka en lista med target parametrar till parametern params för qsharp.estimate funktionen. Kör till exempel samma algoritm med standardparametrarna och de Majorana-baserade qubitparametrarna med ett floquet QEC-schema.

    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 Logiska kvantbitar Logiskt djup T-tillstånd Kodavstånd T-fabriker T-fabriksfraktion Fysiska kvantbitar rQOPS Fysisk körning
    Grindbaserade ns, 10⁻³ 223 3,64 M 4,70 M 21 19 76.30 % 829.77k 26,55 M 31 sek
    Majorana ns, 10⁻⁶ 223 3,64 M 4,70 M 5 19 63.02 % 79.60k 148,67 M 5 sekunder
  2. Du kan också skapa en lista med uppskattningsparametrar med hjälp av EstimatorParams klassen.

    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 Logiska kvantbitar Logiskt djup T-tillstånd Kodavstånd T-fabriker T-fabriksfraktion Fysiska kvantbitar rQOPS Fysisk körning
    Grindbaserade μs, 10⁻³ 223 3,64 M 4,70 M 17 13 40.54 % 216.77k 21.86k 10 timmar
    Grindbaserade μs, 10⁻⁴ 223 3,64 M 4,70 M 9 14 43.17 % 63.57k 41.30k 5 timmar
    Grindbaserade ns, 10⁻³ 223 3,64 M 4,70 M 17 16 69.08 % 416.89k 32,79 M 25 sekunder
    Gate-baserade ns, 10⁻⁴ 223 3,64 M 4,70 M 9 14 43.17 % 63.57k 61,94 M 13 sekunder
    Majorana ns, 10⁻⁴ 223 3,64 M 4,70 M 9 19 82.75 % 501.48k 82.59M 10 sekunder
    Majorana ns, 10⁻⁶ 223 3,64 M 4,70 M 5 13 31.47 % 42.96k 148,67 M 5 sekunder

Köra Pareto-gränsuppskattning

När du beräknar resurserna för en algoritm är det viktigt att överväga kompromissen mellan antalet fysiska kvantbitar och algoritmens körning. Du kan överväga allokering av så många fysiska kvantbitar som möjligt för att minska körningen av algoritmen. Antalet fysiska kvantbitar begränsas dock av antalet fysiska kvantbitar som är tillgängliga i kvantmaskinvaran.

Gränsuppskattningen Pareto ger flera uppskattningar för samma algoritm, var och en med en kompromiss mellan antalet kvantbitar och körningen.

  1. Om du vill köra Resource Estimator med hjälp av Gränsen för Pareto måste du ange parametern "estimateType"target som "frontier". Kör till exempel samma algoritm med de Majorana-baserade kvantbitsparametrarna med en ytkod med hjälp av Pareto-gränsuppskattning.

    result = qsharp.estimate("RunProgram()", params=
                                {"qubitParams": { "name": "qubit_maj_ns_e4" },
                                "qecScheme": { "name": "surface_code" },
                                "estimateType": "frontier", # frontier estimation
                                }
                            )
    
  2. Du kan använda EstimatesOverview funktionen för att visa en tabell med det totala antalet fysiska resurser. Klicka på ikonen bredvid den första raden för att välja de kolumner som du vill visa. Du kan välja mellan körningsnamn, uppskattningstyp, kvantbitstyp, qec-schema, felbudget, logiska kvantbitar, logiskt djup, kodavstånd, T-tillstånd, T-fabriker, T-fabriksfraktion, körning, rQOPS och fysiska kvantbitar.

    from qsharp_widgets import EstimatesOverview
    EstimatesOverview(result)
    

I kolumnen Skattningstyp i resultattabellen kan du se antalet olika kombinationer av {antal qubits, runtime} för din algoritm. I det här fallet hittar Resource Estimator 22 olika optimala kombinationer av många tusen möjliga kombinationer.

Diagram över tidsrymd

Funktionen EstimatesOverview visar också tidsdiagrammet för resursberäknaren.

Diagrammet för tidsrymd visar antalet fysiska kvantbitar och körningen av algoritmen för varje {antal qubits, runtime}-par. Du kan hovra över varje punkt för att se information om resursuppskattningen vid den tidpunkten.

Skärmbild som visar tidsdiagrammet med gränsuppskattning för Resursberäknaren.

Batchbearbetning med Pareto-gränsuppskattning

  1. Lägg till "estimateType": "frontier", parametrarna för att beräkna och jämföra flera konfigurationer av target parametrar med gränsuppskattning.

    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"])
    

    Skärmbild som visar tidsdiagrammet för Resursberäknaren när du använder Pareto-gränsuppskattning och flera konfigurationer av parametrar.

    Kommentar

    Du kan definiera färger och körningsnamn för kvantbitsdiagrammet med hjälp av EstimatesOverview funktionen .

  2. När du kör flera konfigurationer av parametrar med hjälp av target Gränsen för Pareto kan du se resursuppskattningarna för en specifik punkt i tidsdiagrammet, dvs. för varje {antal qubits, runtime}-par. Följande kod visar till exempel användning av uppskattningsinformation för den andra körningen (estimate index=0) och den fjärde (punktindex=3) kortaste körningen.

    EstimateDetails(result[1], 4)
    
  3. Du kan också se blankstegsdiagrammet för en viss punkt i diagrammet för tidsrymd. Följande kod visar till exempel blankstegsdiagrammet för den första körningen av kombinationer (estimate index=0) och den tredje kortaste körningen (punktindex=2).

    SpaceChart(result[0], 2)
    

Förutsättningar för Qiskit

Aktivera Azure Quantum Resource Estimator target på din arbetsyta

Resource Estimator är en target av Microsoft Quantum Computing-providern. Om du har skapat en arbetsyta sedan resursberäknaren släpptes lades Microsoft Quantum Computing-providern till på din arbetsyta automatiskt.

Om du använder en befintlig Azure Quantum-arbetsyta:

  1. Öppna din arbetsyta i Azure-portalen.
  2. Välj Providers under Åtgärder på den vänstra panelen.
  3. Välj + Lägg till en provider.
  4. Välj + Lägg till för Microsoft Quantum Computing.
  5. Välj Learn &Develop (Lär dig och utveckla ) och välj Lägg till.

Skapa en ny notebook-fil på din arbetsyta

  1. Logga in på Azure-portalen och välj din Azure Quantum-arbetsyta.
  2. Under Åtgärder väljer du Notebooks
  3. Klicka på Mina anteckningsböcker och klicka på Lägg till ny
  4. I KernelTyp väljer du IPython.
  5. Skriv ett namn på filen och klicka på Skapa fil.

När den nya notebook-filen öppnas skapas automatiskt koden för den första cellen baserat på din prenumerations- och arbetsyteinformation.

from azure.quantum import Workspace
workspace = Workspace ( 
    resource_id = "", # Your resource_id 
    location = ""  # Your workspace location (for example, "westus") 
)

Kommentar

Om inget annat anges bör du köra varje cell i ordning när du skapar den för att undvika kompileringsproblem.

Klicka på den triangulära uppspelningsikonen till vänster om cellen för att köra koden.

Läs in nödvändiga importer

Först måste du importera ytterligare moduler från azure-quantum och qiskit.

Klicka på + Kod för att lägga till en ny cell och lägg sedan till och kör följande kod:

from azure.quantum.qiskit import AzureQuantumProvider
from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import RGQFTMultiplier

Anslut till Azure Quantum-tjänsten

Skapa sedan ett AzureQuantumProvider-objekt med hjälp av workspace objektet från föregående cell för att ansluta till din Azure Quantum-arbetsyta. Du skapar en serverdelsinstans och anger Resource Estimator som din target.

provider = AzureQuantumProvider(workspace)
backend = provider.get_backend('microsoft.estimator')

Skapa kvantalgoritmen

I det här exemplet skapar du en kvantkrets för en multiplikator baserat på konstruktionen som presenteras i Ruiz-Perez och Garcia-Escartin (arXiv:1411.5949) som använder Quantum Fourier Transform för att implementera aritmetik.

Du kan justera storleken på multiplikatorn genom att ändra variabeln bitwidth . Kretsgenereringen omsluts av en funktion som kan anropas med bitwidth multiplikatorns värde. Åtgärden kommer att ha två indataregister, var och en av de angivna bitwidth, och ett utdataregister som är dubbelt så stort som den angivna bitwidth. Funktionen skriver också ut vissa logiska resursantal för multiplikatorn som extraheras direkt från kvantkretsen.

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

Kommentar

Du kan skicka jobb för uppskattning av fysiska resurser för algoritmer som inte har några T-tillstånd, men som har minst en mätning.

Beräkna kvantalgoritmen

Skapa en instans av algoritmen create_algorithm med hjälp av funktionen. Du kan justera storleken på multiplikatorn genom att ändra variabeln bitwidth .

bitwidth = 4

circ = create_algorithm(bitwidth)

Beräkna de fysiska resurserna för den här åtgärden med hjälp av standardantagandena. Du kan skicka kretsen till resource Estimator-serverdelen med hjälp av run metoden och sedan köra job.result() för att vänta tills jobbet har slutförts och returnera resultatet.

job = backend.run(circ)
result = job.result()
result

Detta skapar en tabell som visar det totala antalet fysiska resurser. Du kan kontrollera kostnadsinformationen genom att komprimera grupperna, som har mer information.

Dricks

Om du vill ha en mer kompakt version av utdatatabellen kan du använda result.summary.

Om du till exempel komprimerar gruppen Logiska kvantbitsparametrar kan du lättare se att felkorrigeringskodavståndet är 15.

Logisk qubit-parameter Värde
QEC-schema surface_code
Kodavstånd 15
Fysiska kvantbitar 450
Logisk cykeltid 6us
Felfrekvens för logisk kvantbit 3.00E-10
Korsande förfaktor 0.03
Tröskelvärde för felkorrigering 0.01
Formel för logisk cykeltid (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime) * codeDistance
Formel för fysiska kvantbitar 2 * codeDistance * codeDistance

I gruppen Fysiska kvantbitsparametrar kan du se de fysiska qubitegenskaper som antogs för den här uppskattningen. Till exempel antas tiden för att utföra en enda kvantbitsmätning och en en qubitsgrind vara 100 ns respektive 50 ns.

Dricks

Du kan också komma åt utdata från Resource Estimator som en Python-ordlista med hjälp av metoden result.data().

Mer information finns i den fullständiga listan över utdata för Resource Estimator.

Blankstegsdiagram

Fördelningen av fysiska kvantbitar som används för algoritmen och T-fabrikerna är en faktor som kan påverka utformningen av algoritmen. Du kan visualisera den här distributionen för att bättre förstå de uppskattade utrymmeskraven för algoritmen.

result.diagram.space

Cirkeldiagram som visar fördelningen av totalt antal fysiska kvantbitar mellan algoritmens kvantbitar och T Factory-kvantbitar. Det finns en tabell med uppdelningen av antalet T-fabrikskopior och antalet fysiska kvantbitar per T-fabrik.

Blankstegsdiagrammet visar andelen kvantbitar för algoritmer och T Factory-kvantbitar. Observera att antalet T-fabrikskopior, 28, bidrar till antalet fysiska kvantbitar för T-fabriker som $\text{T-fabriker} \cdot \text{fysisk qubit per T factory}= 28 \cdot 18 000 = 504 000$.

Mer information finns i Fysisk uppskattning av T-fabriken.

Ändra standardvärdena och uppskatta algoritmen

När du skickar en resursuppskattningsbegäran för ditt program kan du ange några valfria parametrar. Använd fältet jobParams för att komma åt alla värden som kan skickas till jobbkörningen och se vilka standardvärden som antogs:

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'}}

Det här är de target parametrar som kan anpassas:

  • errorBudget – den övergripande tillåtna felbudgeten
  • qecScheme – QEC-schemat (Quantum Error Correction)
  • qubitParams – de fysiska kvantbitsparametrarna
  • constraints – begränsningarna på komponentnivå
  • distillationUnitSpecifications - specifikationerna för algoritmer för destillation av T-fabriker

Mer information finns i Målparametrar för resursberäknaren.

Ändra qubitmodell

Beräkna sedan kostnaden för samma algoritm med hjälp av den Majorana-baserade kvantbitsparametern qubit_maj_ns_e6

job = backend.run(circ,
    qubitParams={
        "name": "qubit_maj_ns_e6"
    })
result = job.result()
result

Du kan inspektera det fysiska antalet programmatiskt. Du kan till exempel utforska information om T-fabriken som skapades för att köra algoritmen.

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]}

Kommentar

Som standard visas körning i nanosekunder.

Du kan använda dessa data för att skapa några förklaringar av hur T-fabrikerna producerar de T-tillstånd som krävs.

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)

Ändra korrigeringsschema för kvantfel

Kör nu resursuppskattningsjobbet igen för samma exempel på De Majorana-baserade qubitparametrarna med ett floqued QEC-schema, qecScheme.

job = backend.run(circ,
    qubitParams={
        "name": "qubit_maj_ns_e6"
    },
    qecScheme={
        "name": "floquet_code"
    })
result_maj_floquet = job.result()
result_maj_floquet

Budget för ändringsfel

Nu kör vi samma kvantkrets igen med errorBudget 10 %.

job = backend.run(circ,
    qubitParams={
        "name": "qubit_maj_ns_e6"
    },
    qecScheme={
        "name": "floquet_code"
    },
    errorBudget=0.1)
result_maj_floquet_e1 = job.result()
result_maj_floquet_e1

Kommentar

Om du stöter på problem när du arbetar med Resursberäknaren kan du gå till sidan Felsökning eller kontakta AzureQuantumInfo@microsoft.com.

Nästa steg