Az erőforrásbecslő futtatásának különböző módjai

Ebben a cikkben az Azure Quantum Resource Estimator használatával ismerkedhet meg. Az erőforrásbecslő a VS Code-ban és online is elérhető Azure Portal.

Az alábbi táblázat az Erőforrásbecslő futtatásának különböző módjait mutatja be.

Felhasználói forgatókönyv Platform Oktatóanyag
Q#-program erőforrásainak becslése Visual Studio Code Válassza a Q# lehetőséget a VS Code-ban az oldal tetején
Q#-program erőforrásainak becslése (speciális) Jupyter Notebook a Visual Studio Code-ban Válassza Jupyter Notebook Q# elemét a lap tetején
Qiskit-program erőforrásainak becslése Azure Quantum Portal Válassza a Qiskit elemet Azure Portal az oldal tetején
QIR-program erőforrásainak becslése Azure Quantum Portal QIR elküldése
FCIDUMP-fájlok használata argumentumparaméterként (speciális) Visual Studio Code Kvantumkémiai probléma beküldése

Megjegyzés

A Microsoft Quantum Development Kit (klasszikus QDK) 2024. június 30. után már nem támogatott. Ha Ön meglévő QDK-fejlesztő, javasoljuk, hogy váltson az új Azure Quantum Development Kitre (Modern QDK) a kvantummegoldások fejlesztésének folytatásához. További információ: A Q#-kód migrálása a modern QDK-ba.

A VS Code előfeltételei

Tipp

A helyi erőforrásbecslő futtatásához nincs szükség Azure-fiókra.

Új Q#-fájl létrehozása

  1. Nyissa meg a Visual Studio Code-ot, és válassza az Új szövegfájl fájlja > lehetőséget egy új fájl létrehozásához.
  2. Mentse a fájlt ShorRE.qs néven. Ez a fájl tartalmazza a program Q#-kódját.

A kvantum-algoritmus létrehozása

Másolja a következő kódot a ShorRE.qs fájlba:

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 LittleEndian 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 by using the `LittleEndian` type.
        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 (as LittleEndian) |𝑦⟩, 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 (as LittleEndian) |𝑦⟩, 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;
    }
}

Az erőforrásbecslő futtatása

A Resource Estimator hat előre definiált qubitparamétert kínál, amelyek közül négy kapualapú utasításkészlettel, kettő pedig Majorana utasításkészlettel rendelkezik. Emellett két kvantum-hibajavítási kódot is kínál, surface_code és floquet_codea .

Ebben a példában az Erőforrásbecslőt a qubit paraméterrel és a qubit_gate_us_e3surface_code kvantumhiba-korrekciós kóddal futtatja.

  1. Válassza a Nézet –> Parancskatalógus lehetőséget, vagy nyomja le a Ctrl+Shift+P billentyűkombinációt, és írja be az "erőforrás" kifejezést, amely a Q#: Erőforrás-becslések kiszámítása lehetőséget jeleníti meg. Válassza ezt a lehetőséget az Erőforrásbecslő ablak megnyitásához.
  2. Választhat egy vagy több Qubit paraméter + Hibajavítás kódtípust az erőforrások becsléséhez. Ebben a példában válassza a qubit_gate_us_e3 lehetőséget, majd kattintson az OK gombra.
  3. Adja meg a Hibakeretet , vagy fogadja el az alapértelmezett 0,001 értéket. Ebben a példában hagyja meg az alapértelmezett értéket, és nyomja le az Enter billentyűt.
  4. Az Enter billentyűt lenyomva fogadja el az alapértelmezett eredménynevet a fájlnév, ebben az esetben a ShorRE alapján.

Az eredmények megtekintése

Az Erőforrásbecslő több becslést is biztosít ugyanahhoz az algoritmushoz, amelyek mindegyike a qubitek száma és a futtatókörnyezet közötti kompromisszumokat jeleníti meg. Az erőforrás-becslés egyik legfontosabb szempontja a futtatókörnyezet és a rendszerskálázás közötti kompromisszum megértése.

Az erőforrás-becslés eredménye megjelenik a Q#-becslés ablakban.

  1. Az Eredmények lapon megjelenik az erőforrás-becslés összegzése. Kattintson az első sor melletti ikonra a megjeleníteni kívánt oszlopok kiválasztásához. Választhat a futtatás neve, a becslés típusa, a qubit típusa, a qec séma, a hibakeret, a logikai qubitek, a logikai mélység, a kód távolsága, a T-állapotok, a T-gyárak, a T-gyári tört, a futtatókörnyezet, az rQOPS és a fizikai qubitek közül.

    Képernyőkép arról, hogyan jelenítheti meg a menüt a választott erőforrás-becslés kimenetének kiválasztásához.

    Az eredménytábla Becslés típusa oszlopában láthatja a(z) {qubitek száma, futtatókörnyezet} optimális kombinációinak számát az algoritmushoz. Ezek a kombinációk a téridő diagramon láthatók.

  2. A Téridő diagram a fizikai qubitek száma és az algoritmus futásideje közötti kompromisszumokat mutatja. Ebben az esetben az erőforrásbecslő több ezer lehetséges kombináció közül 13 különböző optimális kombinációt talál. Az egyes {qubitek, futtatókörnyezet} pontok fölé rámutatva megtekintheti az adott időpontban az erőforrás-becslés részleteit.

    Képernyőkép az Erőforrásbecslő téridő-diagramról.

    További információ: Téridő diagram.

    Megjegyzés

    A térdiagram és az adott pontnak megfelelő erőforrás-becslés részleteinek megtekintéséhez a téridő diagram egy pontjára kell kattintania , azaz {hány qubit, futtatókörnyezet} párra.

  3. A Space diagram az algoritmushoz és a T-gyárakhoz használt fizikai qubitek eloszlását mutatja, amely egy {számú qubit, runtime} párnak felel meg. Ha például a téridő diagram bal szélső pontját választja ki, az algoritmus futtatásához szükséges fizikai qubitek száma 427726, 196686 ezek közül az algoritmus qubitjei, és 231040 a T-gyári qubitek.

    Képernyőkép az Erőforrásbecslő térdiagramról.

  4. Végül az Erőforrás-becslések lapon megjelenik az Erőforrásbecslő kimeneti adatainak teljes listája , amely {több qubit, futtatókörnyezet} párnak felel meg. A költségadatokat a csoportok összecsukásával vizsgálhatja meg, amelyek további információkkal rendelkeznek. Válassza ki például a téridő diagram bal szélső pontját, és csukja össze a Logikai qubit paraméterei csoportot.

    Logikai qubit paraméter Érték
    QEC-séma surface_code
    Kód távolsága 21
    Fizikai qubitek 882
    Logikai ciklus ideje 13 milisecs
    Logikai qubit hibaaránya 3.00E-13
    Átjáróelőtag 0.03
    Hibajavítási küszöbérték 0,01
    Logikai ciklusidő képlete (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime) * codeDistance
    Fizikai qubitek képlete 2 * codeDistance * codeDistance

    Tipp

    Kattintson a Részletes sorok megjelenítése elemre a jelentésadatok egyes kimeneteinek leírásának megjelenítéséhez.

    További információt az Erőforrásbecslő teljes jelentésadataiban talál.

target Paraméterek módosítása

Ugyanannak a Q#-programnak a költségeit más qubittípus, hibajavítási kód és hibakeret használatával becsülheti meg. Nyissa meg az Erőforrás-becslő ablakot a Nézet –> Parancskatalógus gombra kattintva, és írja be a következőt Q#: Calculate Resource Estimates: .

Válasszon ki egy másik konfigurációt, például a Majorana-alapú qubitparamétert. qubit_maj_ns_e6 Fogadja el az alapértelmezett hiba tervezett értékét, vagy írjon be egy újat, és nyomja le az Enter billentyűt. Az Erőforrásbecslő újrafuttatja a becslést az új target paraméterekkel.

További információ: Az erőforrásbecslő célparaméterei .

Paraméterek több konfigurációjának futtatása

Az Azure Quantum Resource Estimator több paraméterkonfigurációt target is futtathat, és összehasonlíthatja az erőforrás-becslés eredményeit.

  1. Válassza a Nézet –> Parancskatalógus lehetőséget, vagy nyomja le a Ctrl+Shift+P billentyűkombinációt, és írja be a parancsot Q#: Calculate Resource Estimates.

  2. Válassza a qubit_gate_us_e3, qubit_gate_us_e4, qubit_maj_ns_e4 + floquet_code és qubit_maj_ns_e6 + floquet_code lehetőséget, majd kattintson az OK gombra.

  3. Fogadja el a 0,001-es hiba alapértelmezett költségvetési értékét, és nyomja le az Enter billentyűt.

  4. Nyomja le az Enter billentyűt a bemeneti fájl (ebben az esetben a ShorRE.qs) elfogadásához.

  5. Több paraméterkonfiguráció esetén az eredmények az Eredmények lapon különböző sorokban jelennek meg.

  6. A Téridő diagram a paraméterek összes konfigurációjának eredményeit mutatja. Az eredménytábla első oszlopa megjeleníti a paraméterek minden konfigurációjának jelmagyarázatát. Az egyes pontokra mutatva megtekintheti az erőforrás-becslés részleteit.

    Képernyőkép a téridő diagramról és az eredmények táblázatáról, amikor több paraméterkonfigurációt futtat az Erőforrás-becslőben.

  7. Kattintson a téridő diagram {number of qubits, runtime} pontjára a megfelelő térdiagram és jelentésadatok megjelenítéséhez.

A VS Code Jupyter Notebook előfeltételei

Tipp

A helyi erőforrásbecslő futtatásához nincs szükség Azure-fiókra.

A kvantum-algoritmus létrehozása

  1. A VS Code-ban válassza a Parancskatalógus megtekintése>, majd a Létrehozás: Új Jupyter Notebook lehetőséget.

  2. A jobb felső sarokban a VS Code észleli és megjeleníti a Python verzióját és a jegyzetfüzethez kiválasztott virtuális Python-környezetet. Ha több Python-környezettel rendelkezik, előfordulhat, hogy ki kell választania egy kernelt a jobb felső sarokban található kernelválasztóval. Ha a rendszer nem észlelt környezetet, a beállítással kapcsolatos információkért tekintse meg a Jupyter Notebooks in VS Code (Jupyter-notebookok a VS Code-ban ) című témakört.

  3. Importálja qsharp a csomagot a jegyzetfüzet első cellájába.

    import qsharp
    
  4. Adjon hozzá egy új cellát, és másolja a következő kódot.

    %%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 LittleEndian 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 by using the `LittleEndian` type.
        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 (as LittleEndian) |𝑦⟩, 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 (as LittleEndian) |𝑦⟩, 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;
    }
    

A kvantum-algoritmus becslése

Most meg kell becsülni a művelet fizikai erőforrásait az RunProgram alapértelmezett feltételezések alapján. Adjon hozzá egy új cellát, és másolja a következő kódot.

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

A qsharp.estimate függvény létrehoz egy eredményobjektumot, amely a fizikai erőforrások összesített számát tartalmazó tábla megjelenítésére használható. A költségadatokat a csoportok összecsukásával vizsgálhatja meg, amelyek további információkkal rendelkeznek. További információért tekintse meg az Erőforrásbecslő teljes jelentésadatait.

Csukja össze például a Logikai qubit paraméterei csoportot annak megtekintéséhez, hogy a kód távolsága 21, a fizikai qubitek száma pedig 882.

Logikai qubit paraméter Érték
QEC-séma surface_code
Kód távolsága 21
Fizikai qubitek 882
Logikai ciklus ideje 8 milisecs
Logikai qubit hibaaránya 3.00E-13
Átkelőelő 0.03
Hibajavítási küszöbérték 0,01
Logikai ciklusidő képlete (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime) * codeDistance
Fizikai qubitek képlete 2 * codeDistance * codeDistance

Tipp

A kimeneti tábla kompaktabb verziójához használhatja a parancsot result.summary.

Térdiagram

Az algoritmushoz és a T-gyárakhoz használt fizikai qubitek eloszlása hatással lehet az algoritmus kialakítására. A csomag segítségével megjelenítheti ezt az qsharp-widgets eloszlást, hogy jobban megértse az algoritmus becsült helyigényét.

from qsharp_widgets import SpaceChart, EstimateDetails
SpaceChart(result)

Ebben a példában az algoritmus futtatásához szükséges fizikai qubitek száma 829766, amelyek közül 196686 algoritmus qubitek, és 633080, amelyek közül t gyári qubitek.

Képernyőkép az Erőforrásbecslő térdiagramról.

Az alapértelmezett értékek módosítása és az algoritmus becslése

Amikor erőforrás-becslési kérelmet küld a programnak, megadhat néhány választható paramétert. A mező használatával jobParams elérheti a target feladat végrehajtásának átadható összes paramétert, és megtekintheti, hogy mely alapértelmezett értékeket feltételezték:

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

Láthatja, hogy az Erőforrás-becslő a qubit_gate_ns_e3 qubitmodellt, a hibajavítási kódot és a surface_code 0,001 hibakeretet használja a becslés alapértelmezett értékeként.

Ezek a target testre szabható paraméterek:

  • errorBudget - az algoritmus általánosan engedélyezett hibakerete
  • qecScheme - a kvantum-hibajavítás (QEC) sémája
  • qubitParams - a fizikai qubit paraméterei
  • constraints - az összetevőszintre vonatkozó korlátozások
  • distillationUnitSpecifications - a T-gyárak desztillációs algoritmusainak specifikációi
  • estimateType - egy vagy határ

További információ: Az erőforrásbecslő célparaméterei .

Qubitmodell módosítása

Ugyanannak az algoritmusnak a költségét a Majorana-alapú qubit paraméterrel becsülheti meg, qubitParams"qubit_maj_ns_e6".

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

Kvantumhiba-korrekciós séma módosítása

Az erőforrás-becslési feladatot újrafuttathatja ugyanahhoz a példához a Majorana-alapú qubitparamétereken egy floqued QEC-sémával( qecScheme).

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

Hibakeret módosítása

Ezután futtassa újra ugyanazt a kvantumcsoportot egy errorBudget 10%-os hibával.

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

Kötegelés az erőforrás-becslővel

Az Azure Quantum Resource Estimator lehetővé teszi a paraméterek több konfigurációjának target futtatását és az eredmények összehasonlítását. Ez akkor hasznos, ha össze szeretné hasonlítani a különböző qubitmodellek, QEC-sémák vagy hibakeretek költségeit.

  1. Kötegelt becslést úgy hajthat végre, hogy átadja a paraméterek listáját target a paramsqsharp.estimate függvény paraméterének. Futtassa például ugyanazt az algoritmust az alapértelmezett paraméterekkel és a Majorana-alapú qubitparaméterekkel egy floqued QEC-sémával.

    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⁻⁶"])
    
    Modellezés Logikai qubitek Logikai mélység T állapotok Kód távolsága T gyárak T gyári tört Fizikai qubitek rQOPS Fizikai futtatókörnyezet
    Kapualapú ns, 10⁻³ 223 3,64 M 4,70 M 21 19 76.30 % 829,77k 26,55 M 31 másodperc
    Majorana ns, 10⁻⁶ 223 3,64 M 4,70 M 5 19 63.02 % 79,60k 148,67 M 5 másodperc
  2. A becslési paraméterek listáját a EstimatorParams osztály használatával is létrehozhatja.

    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)
    
    Modellezés Logikai qubitek Logikai mélység T állapotok Kód távolsága T gyárak T gyári tört Fizikai qubitek rQOPS Fizikai futtatókörnyezet
    Kapualapú μs, 10⁻³ 223 3,64 M 4,70 M 17 13 40.54 % 216,77k 21,86k 10 óra
    Kapualapú μs, 10⁻⁴ 223 3,64 M 4,70 M 9 14 43.17 % 63,57k 41,30k 5 óra
    Kapualapú ns, 10⁻³ 223 3,64 M 4,70 M 17 16 69.08 % 416,89k 32,79 M 25 másodperc
    Kapualapú ns, 10⁻⁴ 223 3,64 M 4,70 M 9 14 43.17 % 63,57k 61,94 M 13 másodperc
    Majorana ns, 10⁻⁴ 223 3,64 M 4,70 M 9 19 82.75 % 501.48k 82,59 M 10 másodperc
    Majorana ns, 10⁻⁶ 223 3,64 M 4,70 M 5 13 31.47 % 42,96k 148,67 M 5 másodperc

Pareto-határbecslés futtatása

Egy algoritmus erőforrásainak becslésekor fontos figyelembe venni a fizikai qubitek száma és az algoritmus futtatókörnyezete közötti kompromisszumot. Az algoritmus futásidejének csökkentése érdekében fontolja meg a lehető legtöbb fizikai qubit lefoglalását. A fizikai qubitek számát azonban a kvantumhardverben elérhető fizikai qubitek száma korlátozza.

A Pareto-határbecslés több becslést is biztosít ugyanahhoz az algoritmushoz, és mindegyiknek meg kell egyeznie a qubitek száma és a futtatókörnyezet között.

  1. Az Erőforrásbecslő Pareto-határbecsléssel történő futtatásához a paramétert a "estimateType"target következőként kell megadnia: "frontier". Futtassa például ugyanazt az algoritmust a Majorana-alapú qubitparaméterekkel egy felületkóddal Pareto-határbecslés használatával.

    result = qsharp.estimate("RunProgram()", params=
                                {"qubitParams": { "name": "qubit_maj_ns_e4" },
                                "qecScheme": { "name": "surface_code" },
                                "estimateType": "frontier", # frontier estimation
                                }
                            )
    
  2. A EstimatesOverview függvénnyel megjelenítheti a fizikai erőforrások összesített számát tartalmazó táblát. Kattintson az első sor melletti ikonra a megjeleníteni kívánt oszlopok kiválasztásához. Választhat a futtatás neve, a becslés típusa, a qubit típusa, a qec séma, a hibakeret, a logikai qubitek, a logikai mélység, a kód távolsága, a T-állapotok, a T-gyárak, a T-gyári tört, a futtatókörnyezet, az rQOPS és a fizikai qubitek közül.

    from qsharp_widgets import EstimatesOverview
    EstimatesOverview(result)
    

Az eredménytábla Becslés típusa oszlopában láthatja az algoritmus {qubitek, futtatókörnyezet} különböző kombinációinak számát. Ebben az esetben az Erőforrásbecslő több ezer lehetséges kombinációból 22 különböző optimális kombinációt talál.

Téridő diagram

A EstimatesOverview függvény az Erőforrásbecslő téridő diagramját is megjeleníti.

A téridő diagram a fizikai qubitek számát és az algoritmus futásidejét mutatja az egyes {number of qubits, runtime} párokhoz. Az egyes pontokra mutatva megtekintheti az erőforrás-becslés részleteit.

Képernyőkép a téridő diagramról az Erőforrásbecslő határbecslésével.

Kötegelés Pareto-határbecsléssel

  1. Ha több paraméterkonfigurációt target szeretne megbecsülni és összehasonlítani a határbecsléssel, adja hozzá "estimateType": "frontier", a paramétereket.

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

    Képernyőkép az Erőforrásbecslő téridő diagramjáról Pareto-határbecslés és több paraméterkonfiguráció használatakor.

    Megjegyzés

    A qubit-time diagram színeit és futtatási nevét a EstimatesOverview függvénnyel határozhatja meg.

  2. Ha több paraméterkonfigurációt target futtat a Pareto-határbecslés használatával, láthatja a téridő diagram egy adott pontjára vonatkozó erőforrás-becsléseket, azaz minden {qubitszám, futtatókörnyezet} párra vonatkozóan. Az alábbi kód például a második (becslési index=0) futtatás becsült adatait és a negyedik (pontindex=3) legrövidebb futásidejű futásidőt mutatja.

    EstimateDetails(result[1], 4)
    
  3. A téridő diagram egy adott pontjára vonatkozó térdiagramot is megtekintheti. Az alábbi kód például a kombinációk első futtatásához (becslési index=0) és a harmadik legrövidebb futtatókörnyezethez (pontindex=2) tartozó térdiagramot mutatja.

    SpaceChart(result[0], 2)
    

A Qiskit előfeltételei

Az Azure Quantum Resource Estimator target engedélyezése a munkaterületen

Az Erőforrásbecslő a target Microsoft Quantum Computing szolgáltató tagja. Ha az Erőforrásbecslő kiadása óta hozott létre munkaterületet, a Microsoft Quantum Computing szolgáltató automatikusan hozzá lett adva a munkaterülethez.

Ha meglévő Azure Quantum-munkaterületet használ:

  1. Nyissa meg a munkaterületet a Azure Portal.
  2. A bal oldali panel Műveletek területén válassza a Szolgáltatók lehetőséget.
  3. Válassza a + Szolgáltató hozzáadása lehetőséget.
  4. Válassza a + Hozzáadás lehetőséget a Microsoft Quantum Computinghoz.
  5. Válassza a Learn & Fejlesztés , majd a Hozzáadás lehetőséget.

Új jegyzetfüzet létrehozása a munkaterületen

  1. Jelentkezzen be a Azure Portal, és válassza ki az Azure Quantum-munkaterületet.
  2. A Műveletek területen válassza a Jegyzetfüzetek lehetőséget
  3. Kattintson a Saját jegyzetfüzetek elemre, majd az Új hozzáadása elemre.
  4. A Kernel típusa területen válassza az IPython lehetőséget.
  5. Írja be a fájl nevét, és kattintson a Fájl létrehozása gombra.

Amikor megnyílik az új jegyzetfüzet, automatikusan létrehozza az első cellához tartozó kódot az előfizetés és a munkaterület adatai alapján.

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

Megjegyzés

Ha másként nem jelezzük, a fordítási problémák elkerülése érdekében az egyes cellákat a létrehozásuk sorrendjében kell futtatnia.

A kód futtatásához kattintson a cella bal oldalán található háromszög alakú "lejátszás" ikonra.

A szükséges importálások betöltése

Először importálnia kell egy további modult a és qiskita modulbólazure-quantum.

Kattintson a + Kód elemre egy új cella hozzáadásához, majd adja hozzá és futtassa a következő kódot:

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

Csatlakozás az Azure Quantum szolgáltatáshoz

Ezután hozzon létre egy AzureQuantumProvider objektumot az workspace előző cella objektumával az Azure Quantum-munkaterülethez való csatlakozáshoz. Hozzon létre egy háttérpéldányt, és állítsa be az Erőforrásbecslőt a következőként: target.

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

A kvantum-algoritmus létrehozása

Ebben a példában a Ruiz-Perezben és a Garcia-Escartin (arXiv:1411.5949) bemutatott szerkezet alapján hoz létre egy kvantum-kapcsolatcsoportot egy szorzóhoz, amely a Quantum Fourier Transform használatával implementálja az aritmetikai műveletet.

A szorzó méretét a változó módosításával módosíthatja bitwidth . A kapcsolatcsoport létrehozása egy függvénybe van csomagolva, amely a bitwidth szorzó értékével hívható meg. A műveletnek két bemeneti regisztere lesz, amelyek mindegyike a megadott bitwidthméretű, és egy kimeneti regiszter, amely kétszer akkora, mint a megadott bitwidth. A függvény a közvetlenül a kvantum-kapcsolatcsoportból kinyert szorzó logikai erőforrás-számát is kinyomtatja.

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

Megjegyzés

Fizikai erőforrás-becslési feladatokat küldhet olyan algoritmusokhoz, amelyek nem rendelkeznek T-állapotokkal, de legalább egy méréssel rendelkeznek.

A kvantum-algoritmus becslése

Hozza létre az algoritmus egy példányát a create_algorithm függvény használatával. A szorzó méretét a változó módosításával módosíthatja bitwidth .

bitwidth = 4

circ = create_algorithm(bitwidth)

Becsülje meg a művelet fizikai erőforrásait az alapértelmezett feltételezések alapján. A metódussal elküldheti a kapcsolatcsoportot az Erőforrás-becslő háttérrendszerbe, majd futtathatja a run parancsot job_monitor a befejezéshez.

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

Ez létrehoz egy táblát, amely a fizikai erőforrások összesített számát mutatja. A költségadatokat a csoportok összecsukásával vizsgálhatja meg, amelyek további információkkal rendelkeznek.

Tipp

A kimeneti tábla kompaktabb verziójához használhatja a parancsot result.summary.

Ha például összecsukja a Logikai qubit paraméterei csoportot, könnyebben láthatja, hogy a hibajavítási kód távolsága 15.

Logikai qubit paraméter Érték
QEC-séma surface_code
Kód távolsága 15
Fizikai qubitek 450
Logikai ciklus ideje 6us
Logikai qubit hibaaránya 3.00E-10
Átkelőelő 0.03
Hibajavítási küszöbérték 0,01
Logikai ciklusidő képlete (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime) * codeDistance
Fizikai qubitek képlete 2 * codeDistance * codeDistance

A Fizikai qubit paraméterei csoportban láthatja a becsléshez feltételezett fizikai qubittulajdonságokat. Az egy qubites mérés és az egy qubites kapu végrehajtásának ideje például 100 ns, illetve 50 ns lehet.

Tipp

Az erőforrásbecslő kimenetét Python-szótárként is elérheti a result.data() metódussal.

További információkért tekintse meg az erőforrásbecslő kimeneti adatainak teljes listáját .

Térdiagramok

Az algoritmushoz és a T-gyárakhoz használt fizikai qubitek eloszlása hatással lehet az algoritmus kialakítására. Ezt az eloszlást vizualizálva jobban megértheti az algoritmus becsült térkövetelményét.

result.diagram.space

Tortadiagram az összes fizikai qubit algoritmus-qubitek és T-gyári qubitek közötti eloszlásáról. Van egy táblázat, amely a T-gyár példányainak számát és a T-előállítónkénti fizikai qubitek számát tartalmazza.

A térdiagram az algoritmus-qubitek és a T-gyári qubitek arányát mutatja. Vegye figyelembe, hogy a T gyári példányok száma (28) a T-gyárak fizikai qubitjeinek számát $\text{T factoryies} \cdot \text{physical qubit per T factory}= 28 \cdot 18 000 = 504 000$ néven adja meg.

További információkért lásd a T factory fizikai becslését ismertető cikket.

Az alapértelmezett értékek módosítása és az algoritmus becslése

Amikor erőforrás-becslési kérelmet küld a programnak, megadhat néhány választható paramétert. A mező használatával jobParams elérheti a feladat végrehajtásának átadható összes értéket, és megtekintheti, hogy mely alapértelmezett értékeket feltételezték:

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

Ezek a target testre szabható paraméterek:

  • errorBudget - az engedélyezett hibák teljes költségvetése
  • qecScheme - a kvantum-hibajavítás (QEC) sémája
  • qubitParams - a fizikai qubit paraméterei
  • constraints - az összetevőszintre vonatkozó korlátozások
  • distillationUnitSpecifications - a T-gyárak desztillációs algoritmusainak specifikációi

További információ: Az erőforrásbecslő célparaméterei .

Qubitmodell módosítása

Ezután becsülje meg ugyanannak az algoritmusnak a költségét a Majorana-alapú qubitparaméter használatával qubit_maj_ns_e6

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

A fizikai számokat programozott módon is megvizsgálhatja. Megismerheti például az algoritmus végrehajtásához létrehozott T-gyár részleteit.

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

Megjegyzés

Alapértelmezés szerint a futtatókörnyezet nanoszekvenciákban jelenik meg.

Ezeket az adatokat arra használhatja, hogy magyarázatot készítsen arról, hogy a T-gyárak hogyan állítják elő a szükséges T-állapotokat.

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)

Kvantumhiba-korrekciós séma módosítása

Most futtassa újra az erőforrás-becslési feladatot ugyanazzal a példával a Majorana-alapú qubitparamétereken egy floqued QEC-sémával( qecScheme).

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

Hibakeret módosítása

Futtassuk újra ugyanazt a kvantumcsoportot egy errorBudget 10%-os hibával.

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

Megjegyzés

Ha problémát tapasztal az Erőforrás-becslő használata során, tekintse meg a Hibaelhárítás oldalt, vagy lépjen kapcsolatba a következővel AzureQuantumInfo@microsoft.com: .

Következő lépések