QuantumKatas/BasicGates/ReferenceImplementation.qs

247 строки
9.0 KiB
Plaintext
Исходник Ответственный История

Этот файл содержит неоднозначные символы Юникода!

Этот файл содержит неоднозначные символы Юникода, которые могут быть перепутаны с другими в текущей локали. Если это намеренно, можете спокойно проигнорировать это предупреждение. Используйте кнопку Экранировать, чтобы подсветить эти символы.

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
//////////////////////////////////////////////////////////////////////
// This file contains reference solutions to all tasks.
// The tasks themselves can be found in Tasks.qs file.
// We recommend that you try to solve the tasks yourself first,
// but feel free to look up the solution if you get stuck.
//////////////////////////////////////////////////////////////////////
namespace Quantum.Kata.BasicGates {
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Canon;
//////////////////////////////////////////////////////////////////
// Part I. Single-Qubit Gates
//////////////////////////////////////////////////////////////////
// Task 1.1. State flip
// Input: A qubit in state |ψ⟩ = α |0⟩ + β |1⟩.
// Goal: Change the state of the qubit to α |1⟩ + β |0⟩.
// Example:
// If the qubit is in state |0⟩, change its state to |1⟩.
// If the qubit is in state |1⟩, change its state to |0⟩.
operation StateFlip_Reference (q : Qubit) : Unit {
body (...) {
X(q);
}
adjoint self;
}
// Task 1.2. Basis change: |0⟩ to |+⟩ and |1⟩ to |-⟩ (and vice versa)
// Input: A qubit in state |ψ⟩ = α |0⟩ + β |1⟩.
// Goal: Change the state of the qubit as follows:
// If the qubit is in state |0⟩, change its state to |+⟩ = (|0⟩ + |1⟩) / sqrt(2).
// If the qubit is in state |1⟩, change its state to |-⟩ = (|0⟩ - |1⟩) / sqrt(2).
// If the qubit is in superposition, change its state according to the effect on basis vectors.
// Note: |+⟩ and |-⟩ form a different basis for single-qubit states, called X basis.
operation BasisChange_Reference (q : Qubit) : Unit {
body (...) {
H(q);
}
adjoint self;
}
// Task 1.3. Sign flip: |+⟩ to |-⟩ and vice versa.
// Inputs: A qubit in state |ψ⟩ = α |0⟩ + β |1⟩.
// Goal: Change the qubit state to α |0⟩ - β |1⟩ (flip the sign of |1⟩ component of the superposition).
operation SignFlip_Reference (q : Qubit) : Unit {
body (...) {
Z(q);
}
adjoint self;
}
// Task 1.4*. Amplitude change (|0⟩ to cos(alpha)*|0⟩ + sin(alpha)*|1⟩).
// Inputs:
// 1) A qubit in state β|0⟩ + γ|1⟩.
// 2) Angle alpha, in radians, represented as Double
// Goal: Change the state of the qubit as follows:
// If the qubit is in state |0⟩, change its state to cos(alpha)*|0⟩ + sin(alpha)*|1⟩.
// If the qubit is in state |1⟩, change its state to -sin(alpha)*|0⟩ + cos(alpha)*|1⟩.
// If the qubit is in superposition, change its state according to the effect on basis vectors.
operation AmplitudeChange_Reference (q : Qubit, alpha : Double) : Unit {
body (...) {
Ry(2.0 * alpha, q);
}
adjoint invert;
}
// Task 1.5. Phase flip
// Input: A qubit in state |ψ⟩ = α |0⟩ + β |1⟩.
// Goal: Change the qubit state to α |0⟩ + iβ |1⟩ (flip the phase of |1⟩ component of the superposition).
operation PhaseFlip_Reference (q : Qubit) : Unit {
body (...) {
S(q);
// alternatively Rz(0.5 * PI(), q);
}
adjoint invert;
}
// Task 1.6*. Phase change
// Inputs:
// 1) A qubit in state β|0⟩ + γ|1⟩.
// 2) Angle alpha, in radians, represented as Double
// Goal: Change the state of the qubit as follows:
// If the qubit is in state |0⟩, don't change its state.
// If the qubit is in state |1⟩, change its state to exp(i*alpha)|1⟩.
// If the qubit is in superposition, change its state according to the effect on basis vectors.
operation PhaseChange_Reference (q : Qubit, alpha : Double) : Unit {
body (...) {
Rz(alpha, q);
}
adjoint invert;
}
// Task 1.7. Bell state change - 1
// Input: Two entangled qubits in Bell state |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2).
// Goal: Change the two-qubit state to |Φ⁻⟩ = (|00⟩ - |11⟩) / sqrt(2).
operation BellStateChange1_Reference (qs : Qubit[]) : Unit {
body (...) {
Z(qs[0]);
// alternatively Z(qs[1]);
}
adjoint invert;
}
// Task 1.8. Bell state change - 2
// Input: Two entangled qubits in Bell state |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2).
// Goal: Change the two-qubit state to |Ψ⁺⟩ = (|01⟩ + |10⟩) / sqrt(2).
operation BellStateChange2_Reference (qs : Qubit[]) : Unit {
body (...) {
X(qs[0]);
// alternatively X(qs[1]);
}
adjoint invert;
}
// Task 1.9. Bell state change - 3
// Input: Two entangled qubits in Bell state |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2).
// Goal: Change the two-qubit state to |Ψ⁻⟩ = (|01⟩ - |10⟩) / sqrt(2).
operation BellStateChange3_Reference (qs : Qubit[]) : Unit {
body (...) {
Y(qs[0]);
}
adjoint invert;
}
//////////////////////////////////////////////////////////////////
// Part II. Multi-Qubit Gates
//////////////////////////////////////////////////////////////////
// Task 2.1. Two-qubit gate - 1
// Input: Two unentangled qubits (stored in an array of length 2).
// The first qubit will be in state |ψ⟩ = α |0⟩ + β |1⟩, the second - in state |0⟩
// (this can be written as two-qubit state (α|0⟩ + β|1⟩) ⊗ |0⟩).
// Goal: Change the two-qubit state to α |00⟩ + β |11⟩.
// Note that unless the starting state of the first qubit was |0⟩ or |1⟩,
// the resulting two-qubit state can not be represented as a tensor product
// of the states of individual qubits any longer; thus the qubits become entangled.
operation TwoQubitGate1_Reference (qs : Qubit[]) : Unit {
body (...) {
CNOT(qs[0], qs[1]);
}
adjoint self;
}
// Task 2.2. Two-qubit gate - 2
// Input: Two qubits (stored in an array of length 2)
// in state |+⟩ ⊗ |+⟩ = (|00⟩ + |01⟩ + |10⟩ + |11⟩) / 2.
// Goal: Change the two-qubit state to (|00⟩ + |01⟩ + |10⟩ - |11⟩) / 2.
// Note that while the starting state can be represented as a tensor product of single-qubit states,
// the resulting two-qubit state can not be represented in such a way.
operation TwoQubitGate2_Reference (qs : Qubit[]) : Unit {
body (...) {
Controlled Z([qs[0]], qs[1]);
}
adjoint self;
}
// Task 2.3. Two-qubit gate - 3
// Input: Two qubits (stored in an array of length 2) in an arbitrary
// two-qubit state α|00⟩ + β|01⟩ + γ|10⟩ + δ|11⟩.
// Goal: Change the two-qubit state to α|00⟩ + γ|01⟩ + β|10⟩ + δ|11⟩.
operation TwoQubitGate3_Reference (qs : Qubit[]) : Unit {
body (...) {
// Hint: this task can be solved using one primitive gate;
// as an exercise, try to express the solution using several controlled Pauli gates.
CNOT(qs[0], qs[1]);
CNOT(qs[1], qs[0]);
CNOT(qs[0], qs[1]);
}
adjoint self;
}
// Task 2.4. Toffoli gate
// Input: Three qubits (stored in an array of length 3) in an arbitrary three-qubit state
// α|000⟩ + β|001⟩ + γ|010⟩ + δ|011⟩ + ε|100⟩ + ζ|101⟩ + η|110⟩ + θ|111⟩.
// Goal: Flip the state of the third qubit if the state of the first two is |11⟩:
// i.e., change the three-qubit state to
// α|000⟩ + β|001⟩ + γ|010⟩ + δ|011⟩ + ε|100⟩ + ζ|101⟩ + θ|110⟩ + η|111⟩.
operation ToffoliGate_Reference (qs : Qubit[]) : Unit {
body (...) {
CCNOT(qs[0], qs[1], qs[2]);
// alternatively (Controlled X)(qs[0..1], qs[2]);
}
adjoint self;
}
// Task 2.5. Fredkin gate
// Input: Three qubits (stored in an array of length 3) in an arbitrary three-qubit state
// α|000⟩ + β|001⟩ + γ|010⟩ + δ|011⟩ + ε|100⟩ + ζ|101⟩ + η|110⟩ + θ|111⟩.
// Goal: Swap the states of second and third qubit if and only if the state of the first qubit is |1⟩:
// i.e., change the three-qubit state to
// α|000⟩ + β|001⟩ + γ|010⟩ + δ|011⟩ + ε|100⟩ + η|101⟩ + ζ|110⟩ + θ|111⟩.
operation FredkinGate_Reference (qs : Qubit[]) : Unit {
body (...) {
Controlled SWAP([qs[0]], (qs[1], qs[2]));
}
adjoint self;
}
}