共用方式為


執行資源估算器的不同方式

在本文中,您將瞭解如何使用 Azure Quantum Resource Estimator。 資源估算器可協助您預估在量子計算機上執行量子程式所需的資源。 您可以使用資源估算器來估計量子位數目、閘道數目,以及執行量子程式所需的電路深度。

資源估算器可在Visual Studio Code 中使用Quantum Development Kit 延伸模組。 如需有關安裝Quantum Development Kit的更多資訊,請參閱

警告

Azure 入口網站中的資源估算器已被取代。 建議您轉換至 Quantum Development Kit中提供的 Visual Studio Code 中的本機資源估算器。

VS Code 的必要條件

提示

您不需要有 Azure 帳戶才能執行資源估算器。

建立新的 Q# 檔案

  1. 開啟 Visual Studio Code,然後選取 [檔案 > 新增文字檔] 以建立新的檔案。
  2. 將檔案儲存為 ShorRE.qs。 此檔案會包含您程式的 Q# 程式碼。

建立量子演算法

將下列程式代碼複製到 ShorRE.qs 檔案中:


    import Std.Arrays.*;
    import Std.Canon.*;
    import Std.Convert.*;
    import Std.Diagnostics.*;
    import Std.Math.*;
    import Std.Measurement.*;
    import Microsoft.Quantum.Unstable.Arithmetic.*;
    import Std.ResourceEstimation.*;

    operation Main() : 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 {
                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) {
            nZeroes += 1;
            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;
    }

執行資源估算器

資源估算器提供 六個預先定義的量子位參數,其中四個具有網關型指令集,以及兩個具有 Majorana 指令集。 它也提供兩個 量子錯誤修正碼surface_codefloquet_code

在此範例中,您會使用 qubit_gate_us_e3 量子位參數和 surface_code 量子錯誤更正碼來執行資源估算器。

  1. 選取 [檢視 -> 命令選擇區],然後輸入 「資源」,其中應該會顯示 Q#:計算資源估計 值選項。 您也可以從作業前顯示的命令清單中按兩下 Main]。 選取此選項以開啟 [資源估算器] 視窗。

    顯示如何從程式代碼鏡頭清單中選取估計命令的螢幕快照。

  2. 您可以選取一或多個 Qubit 參數 + 錯誤更正碼 類型來估計資源。 在此範例中,選取 [qubit_gate_us_e3 ],然後按兩下 [ 確定]。

    顯示如何從 [資源估計] 功能選取量子位參數的螢幕快照。

  3. 指定 錯誤預算 或接受預設值 0.001。 在此範例中,保留預設值,然後按 Enter

  4. Enter 以根據檔名接受預設結果名稱,在此案例中為 ShorRE

查看結果

資源估算器會針對相同的演算法提供多個估計值,每一個都會顯示量子位數目與運行時間之間的取捨。 瞭解運行時間與系統規模之間的取捨是資源估計最重要的層面之一。

資源估計的結果會顯示在 [Q# 估計] 視窗中。

  1. [結果] 索引標籤會顯示資源估計的摘要。 按兩下第一個資料列旁的圖示 ,以選取您想要顯示的數據行。 您可以從執行名稱、估計類型、量子位類型、qec 配置、錯誤預算、邏輯量子位、邏輯深度、程式代碼距離、T 狀態、T Factory、T Factory 分數、運行時間、rQOPS 和實體量子位中選取。

    顯示如何顯示功能表以選取所選資源估計輸出的螢幕快照。

    在結果數據表的 [估計類型] 數據行中,您可以看到演算法 {number of qubit, runtime} 的最佳組合數目。 這些組合可以在時空圖表中看到。

  2. [時空] 圖表會顯示實體量子位數目與演算法運行時間之間的取捨。 在此情況下,資源估算器會從數千個可能的組合中尋找13個不同的最佳組合。 您可以將滑鼠停留在每個 {number of qubits, runtime} 點上,以查看該時間點的資源估計詳細數據。

    顯示資源估算器時空圖表的螢幕快照。

    如需詳細資訊,請參閱 時空圖表

    注意

    您必須 按下某一個空格時間圖表的點 ,也就是 {number of qubits, runtime} pair,以查看空間圖表,以及對應至該點的資源估計詳細數據。

  3. 空間 顯示演算法和 T Factory 所使用的實體量子位分佈,對應至 {number of qubit, runtime} 組。 例如,如果您在時空圖中選取最左邊的點,則執行演算法所需的實體量子位數目427726,其中196686為演算法量子位,其中 231040 為 T Factory 量子位。

    顯示資源估算器空間圖的螢幕快照。

  4. 最後,[ 資源估計 值] 索引卷標會顯示對應至 {number of qubits, runtime} 配對之資源估算器輸出數據的完整清單。 您可以藉由折迭群組來檢查成本詳細資料,這些群組具有詳細資訊。 例如,選取時空圖表中最左邊的點,然後折疊 邏輯量子位參數 群組。

    邏輯量子位元參數
    QEC 配置 surface_code
    程式碼距離 21
    實際量子位元 882
    邏輯週期時間 13 毫秒
    邏輯量子位元錯誤率 3.00E-13
    交叉前置要素 0.03
    錯誤修正臨界值 0.01
    邏輯週期時間公式 (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime) * codeDistance
    實體量子位元公式 2 * codeDistance * codeDistance

    提示

    按兩下 [ 顯示詳細資料列 ] 以顯示報表資料之每個輸出的描述。

    如需詳細資訊,請參閱 資源估算器的完整報表數據。

target變更參數

您可以使用其他量子位類型、錯誤更正碼和錯誤預算來估計相同 Q# 程式的成本。 選取 [檢視 -> 命令選擇區],然後輸入 Q#: Calculate Resource Estimates,以開啟 [資源估算器] 視窗。

選取任何其他組態,例如 Majorana 型量子位參數 qubit_maj_ns_e6。 接受預設錯誤預算值或輸入新的值,然後按 Enter 鍵。 資源估算器會使用新的 target 參數重新執行估計。

如需詳細資訊,請參閱 Target 資源估算器的參數

執行多個參數位列態

Azure Quantum 資源估算器可以執行多個參數位列態 target ,並比較資源估計結果。

  1. 選取 [檢視 -> 命令選擇區],或按 Ctrl+Shift+P,然後輸入 Q#: Calculate Resource Estimates

  2. 選取 [qubit_gate_us_e3]、 [qubit_gate_us_e4]、 [qubit_maj_ns_e4 + floquet_code] 和 [qubit_maj_ns_e6 + floquet_code],然後按兩下 [ 確定]。

  3. 接受預設錯誤預算值 0.001,然後按 Enter

  4. Enter 以接受輸入檔,在此案例中為 ShorRE.qs

  5. 如果是多個參數位列態,結果會顯示在 [結果] 索引卷標的不同數據列中。

  6. [ 時空] 圖表 會顯示所有參數位列態的結果。 結果數據表的第一個數據行會顯示每個參數位態的圖例。 您可以將滑鼠停留在每個點上,以查看該時間點的資源估計詳細數據。

    此螢幕快照顯示在資源估算器中執行多個參數位態時的時間圖表和結果數據表。

  7. 按兩下 空格時間圖表的 {number of qubits, runtime} 點 ,以顯示對應的空間圖表和報表數據。

VS Code 中 Jupyter Notebook 的必要條件

提示

您不需要有 Azure 帳戶才能執行資源估算器。

建立量子演算法

  1. 在 VS Code 中,選取 [檢視]>[命令選擇區],然後選取 [建立:新增 Jupyter Notebook]

  2. 在右上方,VS Code 會偵測並顯示針對筆記本選取的 Python 版本和虛擬 Python 環境。 如果您有多個 Python 環境,您可能需要使用右上方的核心選擇器來選取核心。 如果未偵測到任何環境,請參閱 VS Code 中的 Jupyter Notebook 以取得設定資訊。

  3. 在筆記本的第一個儲存格中,匯入 qsharp 套件。

    import qsharp
    
  4. 新增儲存格並複製下列程式碼。

    %%qsharp
    import Std.Arrays.*;
    import Std.Canon.*;
    import Std.Convert.*;
    import Std.Diagnostics.*;
    import Std.Math.*;
    import Std.Measurement.*;
    import Microsoft.Quantum.Unstable.Arithmetic.*;
    import Std.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 {
                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) {
            nZeroes += 1;
            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;
    }
    

估計量子演算法

現在,您會使用預設假設來估計 RunProgram 作業的實體資源。 新增儲存格並複製下列程式碼。

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

qsharp.estimate 函式會建立結果物件,可用來顯示具有整體實體資源計數的資料表。 您可以展開具有詳細資訊的群組來檢查成本詳細數據。 如需詳細資訊,請參閱 資源估算器的完整報表數據。

例如,展開 邏輯量子位參數 群組,以查看程式代碼距離為 21,而實體量子位的數目為 882。

邏輯量子位元參數
QEC 配置 surface_code
程式碼距離 21
實際量子位元 882
邏輯週期時間 8 千米
邏輯量子位元錯誤率 3.00E-13
交叉前置要素 0.03
錯誤修正臨界值 0.01
邏輯週期時間公式 (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime) * codeDistance
實體量子位元公式 2 * codeDistance * codeDistance

提示

如需更精簡的輸出資料表版本,您可以使用 result.summary

空間圖

演算法和 T Factory 所使用的實體量子位元分佈是可能會影響演算法設計的因素。 您可以使用 qsharp-widgets 套件將此分佈視覺化,以進一步了解演算法的估計空間需求。

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

在此範例中,執行演算法所需的實體量子位元數目 829766,其中 196686 為演算法量子位元,而其中 633080 為 T Factory 量子位元。

顯示資源估算器空間圖的螢幕快照。

變更預設值並估計演算法

提交計劃的資源估計要求時,您可以指定一些選擇性參數。 jobParams使用欄位來存取可傳遞至作業執行的所有target參數,並查看假設的預設值:

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

您可以看到資源估算器會採用 qubit_gate_ns_e3 量子位模型、surface_code 錯誤更正碼和 0.001 錯誤預算作為估計的預設值。

以下是 target 可自訂的參數:

  • errorBudget - 演算法的整體允許錯誤預算
  • qecScheme - 量子誤差修正 (QEC) 配置
  • qubitParams - 實體量子位元參數
  • constraints - 元件層級的條件約束
  • distillationUnitSpecifications - T Factory 擷取演算法的規格。
  • estimateType - 單一或前沿

如需詳細資訊,請參閱 Target 資源估算器的參數

變更量子位元模型

您可以使用以 Majorana 為基礎的量子位元參數,qubitParams,「qubit_maj_ns_e6」 來估計相同演算法的成本。

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

變更量子誤差修正配置

您可以在 Majorana 型的量子位元參數上,使用浮點 QEC 配置,qecScheme,重新執行相同範例的資源估計作業。

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

變更錯誤預算

接下來,使用 10% 的 errorBudget,重新執行相同的量子線路。

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

使用資源估算器進行批處理

Azure Quantum 資源估算器可讓您執行多個參陣列 target 態,並比較結果。 當您想要比較不同量子位元模型、QEC 配置或錯誤預算的成本時,這會很有用。

  1. 您可以將參數清單 target 傳遞至 params 函式的參數 qsharp.estimate ,以執行批次估計。 例如,使用預設參數和以 Majorana 為基礎的量子位參數搭配 floquet QEC 配置來執行相同的演算法。

    result_batch = qsharp.estimate("RunProgram()", params=
                    [{}, # Default parameters
                    {
                        "qubitParams": {
                            "name": "qubit_maj_ns_e6"
                        },
                        "qecScheme": {
                            "name": "floquet_code"
                        }
                    }])
    result_batch.summary_data_frame(labels=["Gate-based ns, 10⁻³", "Majorana ns, 10⁻⁶"])
    
    Model 邏輯量子位元 邏輯深度 T 狀態 程式碼距離 T Factory T Factory 分數 實際量子位元 rQOPS 實際執行時間
    閘道型 ns, 10⁻³ 223 3.64M 4.70M 21 19 76.30 % 829.77k 26.55M 31 秒
    Majorana ns, 10⁻⁶ 223 3.64M 4.70M 5 19 63.02 % 79.60k 148.67M 5 secs
  2. 您也可以使用 EstimatorParams 類別來建構估計參數清單。

    from qsharp.estimator import EstimatorParams, QubitParams, QECScheme, LogicalCounts
    
    labels = ["Gate-based µs, 10⁻³", "Gate-based µs, 10⁻⁴", "Gate-based ns, 10⁻³", "Gate-based ns, 10⁻⁴", "Majorana ns, 10⁻⁴", "Majorana ns, 10⁻⁶"]
    
    params = EstimatorParams(num_items=6)
    params.error_budget = 0.333
    params.items[0].qubit_params.name = QubitParams.GATE_US_E3
    params.items[1].qubit_params.name = QubitParams.GATE_US_E4
    params.items[2].qubit_params.name = QubitParams.GATE_NS_E3
    params.items[3].qubit_params.name = QubitParams.GATE_NS_E4
    params.items[4].qubit_params.name = QubitParams.MAJ_NS_E4
    params.items[4].qec_scheme.name = QECScheme.FLOQUET_CODE
    params.items[5].qubit_params.name = QubitParams.MAJ_NS_E6
    params.items[5].qec_scheme.name = QECScheme.FLOQUET_CODE
    
    qsharp.estimate("RunProgram()", params=params).summary_data_frame(labels=labels)
    
    Model 邏輯量子位元 邏輯深度 T 狀態 程式碼距離 T Factory T Factory 分數 實際量子位元 rQOPS 實際執行時間
    閘道型 µs, 10⁻³ 223 3.64M 4.70M 17 13 40.54 % 216.77k 21.86k 10 個小時
    閘道型 µs, 10⁻⁴ 223 3.64M 4.70M 9 14 43.17 % 63.57k 41.30k 5 個小時
    閘道型 ns, 10⁻³ 223 3.64M 4.70M 17 16 69.08 % 416.89k 32.79M 25 secs
    閘道型 ns, 10⁻⁴ 223 3.64M 4.70M 9 14 43.17 % 63.57k 61.94M 13 secs
    Majorana ns, 10⁻⁴ 223 3.64M 4.70M 9 19 82.75 % 501.48k 82.59M 10 secs
    Majorana ns, 10⁻⁶ 223 3.64M 4.70M 5 13 31.47 % 42.96k 148.67M 5 secs

執行 Pareto 邊境估計

評估演算法的資源時,請務必考慮實體量子位數目與演算法運行時間之間的取捨。 您可以考慮盡可能配置盡可能多的實體量子位,以減少演算法的運行時間。 不過,實體量子位的數目會受限於量子硬體中可用的實體量子位數目。

Pareto 前沿估計會為相同的演算法提供多個估計值,每個演算法在量子位數目與運行時間之間都有取捨。

  1. 若要使用 Pareto 邊際估計來執行資源估算器,您必須將 參數指定 "estimateType"target 為 "frontier"。 例如,使用以Majorana為基礎的量子位參數搭配使用Pareto邊界估計,使用表面程式代碼執行相同的演算法。

    result = qsharp.estimate("RunProgram()", params=
                                {"qubitParams": { "name": "qubit_maj_ns_e4" },
                                "qecScheme": { "name": "surface_code" },
                                "estimateType": "frontier", # frontier estimation
                                }
                            )
    
  2. 您可以使用 函 EstimatesOverview 式來顯示具有整體實體資源計數的數據表。 按兩下第一個資料列旁的圖示,以選取您想要顯示的數據行。 您可以從執行名稱、估計類型、量子位類型、qec 配置、錯誤預算、邏輯量子位、邏輯深度、程式代碼距離、T 狀態、T Factory、T Factory 分數、運行時間、rQOPS 和實體量子位中選取。

    from qsharp_widgets import EstimatesOverview
    EstimatesOverview(result)
    

在結果數據表的 [ 估計類型 ] 數據行中,您可以看到演算法 {number of qubits, runtime} 的不同組合數目。 在此情況下,資源估算器會找出數千個可能組合的 22 個不同最佳組合。

時空圖表

函式 EstimatesOverview 也會顯示 資源估算器的空間時程圖表

時空圖顯示每個 {量子位、運行時間} 組的實體量子位數目和演算法運行時間。 您可以將滑鼠停留在每個點上,以查看該時間點的資源估計詳細數據。

此螢幕快照顯示具有資源估算器邊界估計的時空圖表。

使用 Pareto 邊境估計進行批處理

  1. 若要估計和比較多個參數位列 target 態與前沿估計,請將 新增 "estimateType": "frontier", 至參數。

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

    此螢幕快照顯示使用Pareto邊界估計和多個參數位態時,資源估算器的空間圖表。

    注意

    您可以使用 函式來定義量子位時間圖表 EstimatesOverview 的色彩和執行名稱。

  2. 使用 Pareto 邊界估計執行多個參數組 target 態時,您可以看到空間時程圖表特定時間點的資源估計值,也就是每個 {量子位數目、運行時間} 組。 例如,下列程式代碼會顯示第二個 (estimate index=0) run 和第四個 (point index=3) 最短運行時間的估計詳細數據使用量。

    EstimateDetails(result[1], 4)
    
  3. 您也可以查看空間圖中特定時間點的空間圖表。 例如,下列程式代碼顯示組合第一次執行的空間圖表(estimate index=0)和第三個最短運行時間(point index=2)。

    SpaceChart(result[0], 2)
    

VS Code 中 Qiskit 的必要條件

提示

您不需要有 Azure 帳戶才能執行資源估算器。

創建新的 Jupyter Notebook

  1. 在 VS Code 中,選取 [檢視]>[命令選擇區],然後選取 [建立:新增 Jupyter Notebook]
  2. 在右上方,VS Code 會偵測並顯示針對筆記本選取的 Python 版本和虛擬 Python 環境。 如果您有多個 Python 環境,您可能需要使用右上方的核心選擇器來選取核心。 如果未偵測到任何環境,請參閱 VS Code 中的 Jupyter Notebook 以取得設定資訊。

建立量子演算法

在此範例中,您會根據 Ruiz-Perez 和 Garcia-Escartin (arXiv:1411.5949)呈現的建構來建立乘數的量子電路,其使用 Quantum Fourier Transform 來實作算術。

您可以藉由變更 bitwidth 變數來調整乘數的大小。 線路產生會包裝在可使用 bitwidth 乘數值呼叫的函式中。 此作業會有兩個輸入緩存器,每個輸入緩存器的大小都是指定的 bitwidth,而一個輸出緩存器的大小是指定 bitwidth的大小兩倍。 函式也會列印直接從量子電路擷取之乘數的一些邏輯資源計數。

from qiskit.circuit.library import RGQFTMultiplier 

def create_algorithm(bitwidth):
    print(f"[INFO] Create a QFT-based multiplier with bitwidth {bitwidth}")

    circ = RGQFTMultiplier(num_state_qubits=bitwidth)

    return circ

注意

如果您選取 Python 核心且無法辨識 qiskit 模組,請嘗試在核心選擇器中選取不同的 Python 環境。

估計量子演算法

使用函 create_algorithm 式建立演算法的實例。 您可以藉由變更 bitwidth 變數來調整乘數的大小。

bitwidth = 4

circ = create_algorithm(bitwidth)

使用預設假設估計此作業的實體資源。 您可以使用重載的 estimate 函數,以接受來自 Qiskit 的 QuantumCircuit 物件。

from qsharp.estimator import EstimatorParams
from qsharp.interop.qiskit import estimate

params = EstimatorParams()
result = estimate(circ, params)

或者,您可以使用 ResourceEstimatorBackend 來執行估計,就像現有的後端一樣。

from qsharp.interop.qiskit import ResourceEstimatorBackend
from qsharp.estimator import EstimatorParams

params = EstimatorParams()
backend = ResourceEstimatorBackend()

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

result 物件包含資源估計作業的輸出。 您可以使用 EstimateDetails 函式,以更容易閱讀的格式顯示結果。

from qsharp_widgets import EstimateDetails
EstimateDetails(result)

EstimateDetails 函式會顯示具有整體實體資源計數的數據表。 您可以展開具有詳細資訊的群組來檢查成本詳細數據。 如需詳細資訊,請參閱 資源估算器的完整報表數據。

例如,如果您展開 邏輯量子位參數 群組,您可以更輕鬆地看到錯誤修正碼距離為 15。

邏輯量子位元參數
QEC 配置 surface_code
程式碼距離 15
實際量子位元 450
邏輯週期時間 6us
邏輯量子位元錯誤率 3.00E-10
交叉前置要素 0.03
錯誤修正臨界值 0.01
邏輯週期時間公式 (4 * twoQubitGateTime + 2 * oneQubitMeasurementTime) * codeDistance
實體量子位元公式 2 * codeDistance * codeDistance

在實體 量子位參數 群組中,您可以看到針對此估計所假設的實體量子位屬性。 例如,分別假設執行單一量子位測量和單一量子位閘道的時間是 100 奈秒和 50 奈秒。

提示

您也可以使用 result.data() 方法,以 Python 字典的形式存取資源估算器的輸出。 例如,若要存取實體計數 result.data()["physicalCounts"],可能會執行以下操作。

空間圖

演算法和 T Factory 所使用的實體量子位元分佈是可能會影響演算法設計的因素。 您可以將此分佈可視化,以進一步瞭解演算法的估計空間需求。

from qsharp_widgets import SpaceChart

SpaceChart(result)

餅圖顯示演算法量子位與 T Factory 量子位之間的實體量子位總計分佈。有一個數據表,其中包含 T 處理站複本數目和每個 T Factory 的實體量子位數目。

空間圖顯示演算法量子位和 T Factory 量子位的比例。 請注意,T 工廠的複製數目為 19,該數目會影響每個 T 工廠的實體量子位元總數,因為 $\text{T factories} \cdot \text{physical qubit per T factory} = 19 \cdot 18,000 = 342,000$。

如需詳細資訊,請參閱 T Factory 實體估計

變更預設值並估計演算法

提交計劃的資源估計要求時,您可以指定一些選擇性參數。 jobParams使用欄位來存取可傳遞至作業執行的所有值,並查看假設的預設值:

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

以下是 target 可自訂的參數:

如需詳細資訊,請參閱 Target 資源估算器的參數

變更量子位元模型

接下來,使用Majorana型量子位參數估計相同演算法的成本 qubit_maj_ns_e6

qubitParams = {
    "name": "qubit_maj_ns_e6"
}

result = backend.run(circ, qubitParams).result()

您可以以程式設計方式檢查實體計數。 例如,您可以探索建立以執行演算法之 T Factory 的詳細數據。

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

注意

根據預設,運行時間會顯示在 nanoseconds 中。

您可以使用此資料來產生 T Factory 如何產生必要 T 狀態的一些說明。

data = result.data()
tfactory = data["tfactory"]
breakdown = data["physicalCounts"]["breakdown"]
producedTstates = breakdown["numTfactories"] * breakdown["numTfactoryRuns"] * tfactory["numTstates"]

print(f"""A single T factory produces {tfactory["logicalErrorRate"]:.2e} T states with an error rate of (required T state error rate is {breakdown["requiredLogicalTstateErrorRate"]:.2e}).""")
print(f"""{breakdown["numTfactories"]} copie(s) of a T factory are executed {breakdown["numTfactoryRuns"]} time(s) to produce {producedTstates} T states ({breakdown["numTstates"]} are required by the algorithm).""")
print(f"""A single T factory is composed of {tfactory["numRounds"]} rounds of distillation:""")
for round in range(tfactory["numRounds"]):
    print(f"""- {tfactory["numUnitsPerRound"][round]} {tfactory["unitNamePerRound"][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)

變更量子誤差修正配置

現在,針對以 Majorana 為基礎的量子位參數,使用已壓縮的 QEC 配置,重新執行相同範例的資源估計作業。 qecScheme

params = {
    "qubitParams": {"name": "qubit_maj_ns_e6"},
    "qecScheme": {"name": "floquet_code"}
}

result_maj_floquet = backend.run(circ, params).result()
EstimateDetails(result_maj_floquet)

變更錯誤預算

讓我們以 10% 的 來重新執行相同的量子線路 errorBudget

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

注意

如果您在使用資源估算器時遇到任何問題,請參閱 疑難解答頁面,或連絡 AzureQuantumInfo@microsoft.com

下一步