Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CZ section and CNOT and CZ tasks to Multi-Qubit Gates kata #1389

Merged
merged 23 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9025538
add task2.1 to 2.3
WWhitedogi Apr 15, 2024
51a11b4
Merge branch 'microsoft:main' into task2.1to2.3
WWhitedogi Apr 17, 2024
f397fae
Update katas/content/multi_qubit_gates/index.md
WWhitedogi Apr 17, 2024
8dddd60
Update katas/content/multi_qubit_gates/index.md
WWhitedogi Apr 17, 2024
7c30241
Update katas/content/multi_qubit_gates/index.md
WWhitedogi Apr 17, 2024
ef72bc7
Update katas/content/multi_qubit_gates/two_qubit_gate_2/solution.md
WWhitedogi Apr 17, 2024
52c661f
Update katas/content/multi_qubit_gates/two_qubit_gate_3/solution.md
WWhitedogi Apr 17, 2024
8b5f84b
Update index.md
WWhitedogi Apr 17, 2024
fb8e5b4
Update solution.md
WWhitedogi Apr 17, 2024
bf2a627
Update katas/content/multi_qubit_gates/index.md
WWhitedogi Apr 20, 2024
71e8cd5
Update katas/content/multi_qubit_gates/index.md
WWhitedogi Apr 20, 2024
89b4a0a
Update katas/content/multi_qubit_gates/index.md
WWhitedogi Apr 20, 2024
05f4453
Update katas/content/multi_qubit_gates/index.md
WWhitedogi Apr 20, 2024
5893ed7
Update katas/content/multi_qubit_gates/two_qubit_gate_1/index.md
WWhitedogi Apr 20, 2024
e617323
Update katas/content/multi_qubit_gates/two_qubit_gate_2/Placeholder.qs
WWhitedogi Apr 20, 2024
87bed7f
Update katas/content/multi_qubit_gates/two_qubit_gate_1/Placeholder.qs
WWhitedogi Apr 20, 2024
78c42be
Update katas/content/multi_qubit_gates/two_qubit_gate_2/Placeholder.qs
WWhitedogi Apr 20, 2024
29904eb
Update katas/content/multi_qubit_gates/two_qubit_gate_1/solution.md
WWhitedogi Apr 20, 2024
a963a37
Update katas/content/multi_qubit_gates/two_qubit_gate_2/solution.md
WWhitedogi Apr 20, 2024
ad7f39e
Update katas/content/multi_qubit_gates/two_qubit_gate_2/solution.md
WWhitedogi Apr 20, 2024
5986727
update task2.1to2.3
WWhitedogi Apr 21, 2024
50b304b
Update katas/content/multi_qubit_gates/relative_phase_minusone/Verifi…
tcNickolas Apr 22, 2024
7ba5ada
Update katas/content/multi_qubit_gates/index.md
tcNickolas Apr 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Kata {
operation EntangleQubits (qs : Qubit[]) : Unit is Adj + Ctl {
// Implement your solution here...

}
}
5 changes: 5 additions & 0 deletions katas/content/multi_qubit_gates/entangle_qubits/Solution.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace Kata {
operation EntangleQubits (qs : Qubit[]) : Unit is Adj + Ctl {
CNOT(qs[0], qs[1]);
}
}
52 changes: 52 additions & 0 deletions katas/content/multi_qubit_gates/entangle_qubits/Verification.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
namespace Kata.Verification {
open Microsoft.Quantum.Katas;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Convert;

operation EntangleQubits (qs : Qubit[]) : Unit is Adj + Ctl {
CNOT(qs[0], qs[1]);
}

operation CheckOperationsEquivalenceOnInitialStateStrict(
initialState : Qubit[] => Unit is Adj,
op : (Qubit[] => Unit is Adj + Ctl),
reference : (Qubit[] => Unit is Adj + Ctl),
inputSize : Int
) : Bool {
use (control, target) = (Qubit(), Qubit[inputSize]);
within {
H(control);
initialState(target);
}
apply {
Controlled op([control], target);
Adjoint Controlled reference([control], target);
}
let isCorrect = CheckAllZero([control] + target);
ResetAll([control] + target);
isCorrect
}

operation CheckSolution() : Bool {
let range = 10;
for i in 0 .. range - 1 {
let angle = 2.0 * PI() * IntAsDouble(i) / IntAsDouble(range);
let initialState = qs => Ry(2.0 * angle, qs[0]);
let isCorrect = CheckOperationsEquivalenceOnInitialStateStrict(
initialState,
Kata.EntangleQubits,
EntangleQubits,
2);
if not isCorrect {
Message("Incorrect");
Message($"Test fails for alpha = {Cos(angle)}, beta = {Sin(angle)}.");
ShowQuantumStateComparison(2, initialState, Kata.EntangleQubits, EntangleQubits);
return false;
}
}

Message("Correct!");
true
}
}
5 changes: 5 additions & 0 deletions katas/content/multi_qubit_gates/entangle_qubits/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**Input:** Two unentangled qubits (stored in an array of length 2).
The first qubit will be in state $|\psi\rangle = \alpha |0\rangle + \beta |1\rangle$, the second - in state $|0\rangle$
(this can be written as two-qubit state $\big(\alpha |0\rangle + \beta |1\rangle \big) \otimes |0\rangle = \alpha |00\rangle + \beta |10\rangle$).

**Goal:** Change the two-qubit state to $\alpha |00\rangle + \beta |11\rangle$.
11 changes: 11 additions & 0 deletions katas/content/multi_qubit_gates/entangle_qubits/solution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Let's denote the first qubit in state $\alpha |0\rangle + \beta |1\rangle$ as A and the second qubit in state $|0\rangle$ as B.

Compare our input state $\alpha |0_A0_B\rangle + \beta |1_A0_B\rangle$ with the goal state $\alpha |0_A0_B\rangle + \beta |1_A1_B\rangle$.
We want to pass our input qubit through a gate or gates (to be decided) that do the following. If qubit A is in the $|0\rangle$ state, then we want to leave qubit B alone (the first term of the superposition).
However, if A is in the $|1\rangle$ state, we want to flip qubit B from $|0\rangle$ into $|1\rangle$ state. In other words, the state of B is to be made contingent upon the state of A.
This is exactly the effect of the $CNOT$ gate. Depending upon the state of the **control** qubit (A in our case), the value of the controlled or **target** qubit (B in our case) is inverted or unchanged. Thus, we get the goal state $\alpha |00\rangle + \beta |11\rangle$.

@[solution]({
"id": "multi_qubit_gates__entangle_qubits_solution",
"codePath": "./Solution.qs"
})
66 changes: 66 additions & 0 deletions katas/content/multi_qubit_gates/index.md
tcNickolas marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@ $$\alpha|00\rangle + \beta|11\rangle$$

The $CNOT$ gate is self-adjoint: applying it for the second time reverses its effect.


@[exercise]({
"id": "multi_qubit_gates__entangle_qubits",
"title": "Entangle Qubits",
"path": "./entangle_qubits/",
"qsDependencies": [
"../KatasLibrary.qs"
]
})

@[exercise]({
"id": "multi_qubit_gates__preparing_bell_state",
"title": "Preparing a Bell State",
Expand All @@ -130,6 +140,62 @@ The $CNOT$ gate is self-adjoint: applying it for the second time reverses its ef
]
})

@[section]({
"id": "multi_qubit_gates__cz_gate",
"title": "CZ Gate"
})


The $CZ$ ("controlled-Z") gate is a two-qubit gate, with one qubit referred to as the **control** qubit, and the other as the **target** qubit. Interestingly, for the $CZ$ gate it doesn't matter which qubit is control and which is target - the effect of the gate is the same either way!

The $CZ$ gate acts as a conditional gate: if the control qubit is in state $|1\rangle$, it applies the $Z$ gate to the target qubit, otherwise it does nothing.

<table>
<tr>
<th>Gate</th>
<th>Matrix</th>
<th>Applying to $|\psi\rangle = \alpha|00\rangle + \beta|01\rangle + \gamma|10\rangle + \delta|11\rangle$</th>
<th>Applying to basis states</th>
</tr>
<tr>
<td>$CZ$</td>
<td>
$$\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & -1
\end{bmatrix}$$
</td>
<td>$CZ|\psi\rangle = \alpha|00\rangle + \beta|01\rangle + \gamma|10\rangle - \delta|11\rangle$</td>
<td>
$$CZ|00\rangle = |00\rangle$$
$$CZ|01\rangle = |01\rangle$$
$$CZ|10\rangle = |10\rangle$$
$$CZ|11\rangle = -|11\rangle$$
</td>
</tr>
</table>

The $CZ$ gate is particularly useful for creating and manipulating entangled states where the phase of the quantum state is crucial. Consider the following separable state:

$$\big(\alpha|0\rangle + \beta|1\rangle\big) \otimes \big(\gamma|0\rangle + \delta|1\rangle\big) = \alpha\gamma|00\rangle + \alpha\delta|01\rangle + \beta\gamma|10\rangle + \beta\delta|11\rangle$$

If we apply the $CZ$ gate to it, with the first qubit as the control and the second as the target (or vice versa), we get the following state, which can no longer be separated:

$$\alpha\gamma|00\rangle + \alpha\delta|01\rangle + \beta\gamma|10\rangle - \beta\delta|11\rangle$$

The $CZ$ gate is also self-adjoint: applying it a second time reverses its effect, similar to the $CNOT$ gate.

@[exercise]({
tcNickolas marked this conversation as resolved.
Show resolved Hide resolved
"id": "multi_qubit_gates__relative_phase_minusone",
"title": "Relative Phase -1",
"path": "./relative_phase_minusone/",
"qsDependencies": [
"../KatasLibrary.qs"
]
})

@[section]({
"id": "multi_qubit_gates__ket_bra_representation",
"title": "Ket-Bra Representation"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Kata {
operation RelativePhaseMinusOne (qs : Qubit[]) : Unit is Adj + Ctl {
// Implement your solution here...

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace Kata {
operation RelativePhaseMinusOne (qs : Qubit[]) : Unit is Adj + Ctl {
CZ(qs[0], qs[1]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace Kata {
operation RelativePhaseMinusOne (qs : Qubit[]) : Unit is Adj + Ctl {
Controlled Z([qs[0]], qs[1]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
namespace Kata.Verification {
open Microsoft.Quantum.Katas;
open Microsoft.Quantum.Diagnostics;

operation PrepareState(qs : Qubit[]) : Unit is Adj + Ctl {
ApplyToEachCA(H, qs);
}
operation RelativePhaseMinusOne (qs : Qubit[]) : Unit is Adj + Ctl {
CZ(qs[0], qs[1]);
}

operation CheckOperationsEquivalenceOnInitialStateStrict(
initialState : Qubit[] => Unit is Adj,
op : (Qubit[] => Unit is Adj + Ctl),
reference : (Qubit[] => Unit is Adj + Ctl),
inputSize : Int
) : Bool {
use (control, target) = (Qubit(), Qubit[inputSize]);
within {
H(control);
initialState(target);
}
apply {
Controlled op([control], target);
Adjoint Controlled reference([control], target);
}
let isCorrect = CheckAllZero([control] + target);
ResetAll([control] + target);
isCorrect
}

operation CheckSolution() : Bool {
let isCorrect = CheckOperationsEquivalenceOnInitialStateStrict(
PrepareState,
Kata.RelativePhaseMinusOne,
RelativePhaseMinusOne,
2);
if isCorrect {
Message("Correct!");
} else {
Message("Incorrect");
ShowQuantumStateComparison(2, PrepareState, Kata.RelativePhaseMinusOne, RelativePhaseMinusOne);
}

return isCorrect;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**Input:** Two unentangled qubits (stored in an array of length 2) in state $|+\rangle \otimes |+\rangle = \frac{1}{2} \big( |00\rangle + |01\rangle + |10\rangle {\color{blue}+} |11\rangle \big)$.

**Goal:** Change the two-qubit state to $\frac{1}{2} \big( |00\rangle + |01\rangle + |10\rangle {\color{red}-} |11\rangle \big)$.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Firstly we notice that we are dealing with an unentangled pair of qubits.
In vector form the transformation we need is
$$
\frac{1}{2}\begin{bmatrix}1\\\ 1\\\ 1\\\ 1\\\ \end{bmatrix}
\rightarrow
\frac{1}{2}\begin{bmatrix}1\\\ 1\\\ 1\\\ -1\\\ \end{bmatrix}
$$

All that needs to happen to change the input into the goal is that the $|11\rangle$ basis state needs to have its sign flipped.

We remember that the Pauli $Z$ gate flips signs in the single qubit case, and that $CZ$ is the 2-qubit version of this gate. And indeed, the effect of the $CZ$ gate is exactly the transformation we're looking for here.

@[solution]({
"id": "multi_qubit_gates__two_qubit_gate_2_solution_a",
"codePath": "./SolutionA.qs"
})
Alternatively, we can express this gate using the intrinsic gate Z and its controlled variant using the Controlled functor:

@[solution]({
"id": "multi_qubit_gates__two_qubit_gate_2_solution_b",
"codePath": "./SolutionB.qs"
})
Loading