Práce s QubitsWorking with Qubits

Teď se zobrazila celá řada různých částí jazyka Q #. můžeme se dostat do široké nabídky a podívat se, jak qubits sami.Having now seen a variety of different parts of the Q# language, let us get into the thick of it and see how to use qubits themselves.

Přidělování QubitsAllocating Qubits

Nejprve pro získání qubit, které můžeme použít ve Q #, přidělíme qubits v rámci usingho bloku:First, to obtain a qubit that we can use in Q#, we allocate qubits within a using block:

using (register = Qubit[5]) {
    // Do stuff...
}

Libovolný qubits přidělený tímto způsobem začal ve stavu $ \ket{0}$; ve výše uvedeném příkladu je register tak ve stavu $ \ket{00000} = \ket{0} \otimes \ket{0} \otimes \cdots \otimes \ket{0}$.Any qubits allocated in this way start off in the $\ket{0}$ state; in the example above, register is thus in the state $\ket{00000} = \ket{0} \otimes \ket{0} \otimes \cdots \otimes \ket{0}$. Na konci using bloku jsou všechny qubits přidělené tímto blokem okamžitě uvolněny a nelze je použít dále.At the end of the using block, any qubits allocated by that block are immediately deallocated and cannot be used further.

Varování

Cílové počítače očekávají, že qubits jsou ve stavu $ \ket{0}$ bezprostředně před zrušením přidělení, aby je bylo možné znovu použít a nabízet k ostatním usingm blokům pro přidělení.Target machines expect that qubits are in the $\ket{0}$ state immediately before deallocation, so that they can be reused and offered to other using blocks for allocation. Kdykoli je to možné, použijte k vrácení všech přidělených qubits do $ \ket{0}$ jednotnou operaci.Whenever possible, use unitary operations to return any allocated qubits to $\ket{0}$. V případě potřeby je možné místo toho použít operaci Reset k měření qubit a k použití tohoto výsledku měření, abyste zajistili, že se měřený qubit vrátí do $ \ket{0}$.If need be, the Reset operation can be used to measure a qubit instead, and to use that measurement result to ensure that the measured qubit is returned to $\ket{0}$. Taková míra odstraní všechny entanglement se zbývajícími qubits a může tedy ovlivnit výpočet.Such a measurement will destroy any entanglement with the remaining qubits and can thus impact the computation.

Vnitřní operaceIntrinsic Operations

Po přidělení může být qubit předán do funkcí a operací.Once allocated, a qubit can then be passed to functions and operations. V některých případech to znamená, že program Q # může s qubit provádět, protože akce, které lze provést, jsou definovány jako operace.In some sense, this is all that a Q# program can do with a qubit, as the actions that can be taken are all defined as operations. Tyto operace podrobněji uvidíme v vnitřních operacích a funkcích, ale v současné době uvádíme několik užitečných operací, které se dají použít k interakci s qubits.We will see these operations in more detail in Intrinsic Operations and Functions, but for now, we mention a few useful operations that can be used to interact with qubits.

Za prvé, qubit Pauli Operators $X $, $Y $ a $Z $ jsou v Q # reprezentovány vnitřními operacemi X, Ya Z, z nichž každý má typ (Qubit => Unit is Adj + Ctl).First, the single-qubit Pauli operators $X$, $Y$, and $Z$ are represented in Q# by the intrinsic operations X, Y, and Z, each of which has type (Qubit => Unit is Adj + Ctl). Jak je popsáno v tématu vnitřní operace a funkce, můžeme si představit $X $ a proto se X jako operace překlápění nebo ne jako hradlo.As described in Intrinsic Operations and Functions, we can think of $X$ and hence of X as a bit-flip operation or NOT gate. To umožňuje připravit stavy formuláře $ \ket{s_0 s_1 \dots s_n} $ pro některý z klasických bitových řetězců $s $:This lets us prepare states of the form $\ket{s_0 s_1 \dots s_n}$ for some classical bit string $s$:

operation PrepareBitString(bitstring : Bool[], register : Qubit[]) : Unit 
is Adj + Ctl {

    let nQubits = Length(register);
    for (idxQubit in 0..nQubits - 1) {
        if (bitstring[idxQubit]) {
            X(register[idxQubit]);
        }
    }
}

operation Example() : Unit {

    using (register = Qubit[8]) {
        PrepareBitString(
            [true, true, false, false, true, false, false, true],
            register
        );
        // At this point, register now has the state |11001001〉.
    }
}

Tip

Později se zobrazí více kompaktních způsobů psaní této operace, která nevyžaduje ruční řízení toku.Later, we will see more compact ways of writing this operation that do not require manual flow control.

Také je možné připravit stavy, jako je $ \ket{+} = \left (\ket{0} + \ket{1}\right)/\sqrt{2}$ a $ \ket{-} = \left (\ket{0}-\ket{1}\right)/\sqrt{2}$ pomocí Hadamard Transform $H $, který je reprezentován v Q # vnitřní operací H : (Qubit => Unit is Adj + Ctl):We can also prepare states such as $\ket{+} = \left(\ket{0} + \ket{1}\right) / \sqrt{2}$ and $\ket{-} = \left(\ket{0} - \ket{1}\right) / \sqrt{2}$ by using the Hadamard transform $H$, which is represented in Q# by the intrinsic operation H : (Qubit => Unit is Adj + Ctl):

operation PreparePlusMinusState(bitstring : Bool[], register : Qubit[]) : Unit {

    // First, get a computational basis state of the form
    // |s_0 s_1 ... s_n〉 by using PrepareBitString, above.
    PrepareBitString(bitstring, register);
    // Next, we use that |+〉 = H|0〉 and |-〉 = H|1〉 to
    // prepare the state we want.
    for (idxQubit in IndexRange(register)) {
        H(register[idxQubit]);
    }
}

MěřeníMeasurements

Pomocí operace Measure, která je vestavěnou vnitřní nejednotkovou operací, můžeme extrahovat klasické informace z objektu typu Qubit a přiřadit klasický údaj jako výsledek, který má rezervovaný typ Result, což značí, že výsledek již není v nestránkovaném stavu.Using the Measure operation, which is a built in intrinsic non-unitary operation, we can extract classical information from an object of type Qubit and assign a classical value as a result, which has a reserved type Result, indicating that the result is no longer a quantum state. Vstup pro Measure je Pauli osa v koule Bloch, reprezentovaná objektem typu Pauli (tj. pro instanci PauliX) a objektem typu Qubit.The input to Measure is a Pauli axis on the Bloch sphere, represented by an object of type Pauli (i.e., for instance PauliX) and an object of type Qubit.

Jednoduchým příkladem je následující operace, která vytvoří jeden qubit ve stavu $ \ket{0}$, pak na něj použije H bránu Hadamard a pak výsledek měří na základě PauliZ.A simple example is the following operation which creates one qubit in the $\ket{0}$ state, then applies a Hadamard gate H to it and then measures the result in the PauliZ basis.

operation MeasurementOneQubit () : Result {

    // The following using block creates a fresh qubit and initializes it 
    // in the |0〉 state.
    using (qubit = Qubit()) {
        // We apply a Hadamard operation H to the state, thereby creating the 
        // state 1/sqrt(2)(|0〉+|1〉). 
        H(qubit); 
        // Now we measure the qubit in Z-basis.
        let result = M(qubit);
        // As the qubit is now in an eigenstate of the measurement operator, 
        // we reset the qubit before releasing it. 
        if (result == One) { X(qubit); }   
        // Finally, we return the result of the measurement. 
        return result;
    }
}

Mírně složitější příklad je dán následující operací, která vrací logickou hodnotu true, pokud všechny qubits v registru typu Qubit[] jsou v hodnotě nula, pokud se měří v zadaném Pauli a false jinak.A slightly more complicated example is given by the following operation which returns the Boolean value true if all qubits in a register of type Qubit[] are in the state zero, when measured in a specified Pauli basis and false otherwise.

operation AllMeasurementsZero (qs : Qubit[], pauli : Pauli) : Bool {

    mutable value = true;
    for (q in qs) {
        if ( Measure([pauli], [q]) == One ) {
            set value = false;
        }
    }
    return value;
}

Jazyk Q # umožňuje závislosti toku klasického řízení při měření výsledků qubits.The Q# language allows dependencies of classical control flow on measurement results of qubits. To zase umožňuje implementovat výkonné pravděpodobnostní miniaplikace, které mohou snížit výpočetní náklady na implementaci unitaries.This in turn enables to implement powerful probabilistic gadgets that can reduce the computational cost for implementing unitaries. Jako příklad se dá snadno implementovat volání Repeat-to-do- v Q #, které představují pravděpodobnostní okruhy s očekávanými nízkými náklady z hlediska základních bran, ale u kterých skutečné náklady závisí na skutečném běhu a skutečném prochodu různých možných rozvětvení.As an example, it is easy to implement so-called Repeat-Until-Success in Q# which are probabilistic circuits that have an expected low cost in terms of elementary gates, but for which the true cost depends on an actual run and an actual interleaving of various possible branchings.

Aby bylo možné zjednodušit vzorce opakování až do úspěchu (ru), Q # podporuje konstrukt.To facilitate Repeat-Until-Success (RUS) patterns, Q# supports the construct

repeat {
    statementBlock1 
}
until (expression)
fixup {
    statementBlock2
}

kde statementBlock1 a statementBlock2 jsou nula nebo více příkazů Q # a expression libovolný platný výraz, který je vyhodnocen na hodnotu typu Bool.where statementBlock1 and statementBlock2 are zero or more Q# statements, and expression any valid expression that evaluates to a value of type Bool. V typickém případu použití následující okruh implementuje otočení kolem osy Irrational $ (I + 2i Z)/\sqrt{5}$ v koule Bloch.In a typical use case, the following circuit implements a rotation around an irrational axis of $(I + 2i Z)/\sqrt{5}$ on the Bloch sphere. Toho je možné dosáhnout pomocí známého vzoru ru:This is accomplished by using a known RUS pattern:

operation RUScircuit (qubit : Qubit) : Unit {

    using(ancillas = Qubit[2]) {
        ApplyToEachA(H, ancillas);
        mutable finished = false;
        repeat {
            Controlled X(ancillas, qubit);
            S(qubit);
            Controlled X(ancillas, qubit);
            Z(qubit);
        }
        until(finished)
        fixup {
            if AllMeasurementsZero(ancillas, Xpauli) {
                set finished = true;
            }
        }
    }
}

Tento příklad ukazuje použití proměnlivé proměnné finished, která je v rozsahu celého cyklu opakování až do opravy a která je inicializována před smyčkou a aktualizována v kroku opravy.This example shows the use of a mutable variable finished which is in scope of the entire repeat-until-fixup loop and which gets initialized before the loop and updated in the fixup step.

Nakonec ukážeme příklad ru vzoru pro přípravu stavového pole $ \frac{1}{\sqrt{3}} \left (\sqrt{2}\ket{0}+ \ket{1}\right) $, počínaje ze stavu $ \ket{+} $.Finally, we show an example of a RUS pattern to prepare a quantum state $\frac{1}{\sqrt{3}}\left(\sqrt{2}\ket{0}+\ket{1}\right)$, starting from the $\ket{+}$ state. Viz také ukázkový test jednotek, který je součástí standardní knihovny:See also the unit testing sample provided with the standard library:

operation RepeatUntilSuccessStatePreparation( target : Qubit ) : Unit {

    using( ancilla = Qubit() ) {
        H(ancilla);
        repeat {
            // We expect target and ancilla qubit to be in |+⟩ state.
            AssertProb( 
                [PauliX], [target], Zero, 1.0, 
                "target qubit should be in the |+⟩ state", 1e-10 );
            AssertProb( 
                [PauliX], [ancilla], Zero, 1.0,
                "ancilla qubit should be in the |+⟩ state", 1e-10 );
                
            Adjoint T(ancilla);
            CNOT(target, ancilla);
            T(ancilla);

            // The probability of measuring |+⟩ state on ancilla is 3/4.
            AssertProb( 
                [PauliX], [ancilla], Zero, 3. / 4., 
                "Error: the probability to measure |+⟩ in the first 
                ancilla must be 3/4",
                1e-10);

            // If we get measurement outcome Zero, we prepare the required state 
            let outcome = Measure([PauliX], [ancilla]);
        }
        until( outcome == Zero )
        fixup {
            // Bring ancilla and target back to |+⟩ state
            if( outcome == One ) {
                Z(ancilla);
                X(target);
                H(target);
            }
        }
        // Return ancilla back to Zero state
        H(ancilla);
    }
}

Významné programové funkce uvedené v této operaci jsou složitější fixup součástí smyčky, která zahrnuje operace s nenáročnými na sebe, a použití příkazů AssertProb k zjištění pravděpodobnosti měření stavu nečinnosti v určitých bodech v programu.Notable programmatic features shown in this operation are a more complex fixup part of the loop which involves quantum operations, and the use of AssertProb statements to ascertain the probability of measuring the quantum state at certain specified points in the program. Další informace o Assert a AssertProbch příkazech naleznete v tématu testování a ladění .See also Testing and debugging for more information about Assert and AssertProb statements.