Quantum Challenge 2023 Spring Lab1解答紹介

## Quantum Challenge 2023 Spring　解説
2023年5月に開催されたQuantum Challenge 2023 Springの解説をしていきます。
今回はまずLab1について扱います。

Quantum Challengeは、IBM Quantum Labのオンラインの環境で問題を閲覧し、その場で解答を入力することで誰でも参加できます。

#### Lab1-1

導入として、以下の回路を表すコードが紹介されています。Quantum Challengeはこのように大変参考になる導入がああるので、とても取り組みやすと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322756/e4c52edb-55f1-de6e-b142-897ef88e749c.png)

```Python
from qiskit import QuantumCircuit
from qiskit.circuit import QuantumRegister, ClassicalRegister

qr = QuantumRegister(1)
cr = ClassicalRegister(2)
qc = QuantumCircuit(qr, cr)

# unpack the qubit and classical bits from the registers
(q0,) = qr
b0, b1 = cr

# apply Hadamard
qc.h(q0)
# measure
qc.measure(q0, b0)

# begin if test block. the contents of the block are executed if b0 == 1
with qc.if_test((b0, 1)):
    # if the condition is satisfied (b0 == 1), then flip the bit back to 0
    qc.x(q0)
# finally, measure q0 again
qc.measure(q0, b1)

qc.draw(output="mpl", idle_wires=False)
```
これを実行すると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322756/cf0187cd-c664-0da4-201f-5c2cef7a2925.png)
となります。

問いに入ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322756/89442eab-4480-6f63-3cc9-96eb77c6bb49.png)

解答欄として、
```Python
qr = QuantumRegister(2)
cr = ClassicalRegister(2)
qc = QuantumCircuit(qr, cr)

q0, q1 = qr
b0, b1 = cr

qc.h(q0)
qc.measure(q0, b0)

####### your code goes here #######


qc.measure(q1, b1)
qc.draw(output="mpl", idle_wires=False)
```

が用意されており、####### your code goes here #######の部分のみ追記します。
アダマールゲートを作用させ、q0を測定するところまでは書かれているので、その結果によってq1にXゲート、もしくはアダマールゲートを作用させるコードを書きます。

q0の測定結果による条件の分岐には、if_test()文を使います。
```Python
with qc.if_test((0, 0)) as else_:
    # if the condition is satisfied (b0 == 1), then flip the bit back to 0
    qc.x(1)
with else_:
    # if the condition is satisfied (b0 == 1), then flip the bit back to 0
    qc.h(1)
```
これを実行すると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322756/ab97c5a5-30fe-ecd2-d2f3-2f7b77356b6c.png)

が得られます。

#### Lab1-2
次の問題は、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322756/218a0d13-b240-fff0-4037-e7c046cc2545.png)
こちらの回路を記述することです。背景はQuantum Challengeの問題をぜひご覧ください。
ここでは、予めベースとして以下の回路が与えられていました。

```Python
controls = QuantumRegister(2, name="control")
target = QuantumRegister(1, name="target")

mid_measure = ClassicalRegister(2, name="mid")
final_measure = ClassicalRegister(1, name="final")

base = QuantumCircuit(controls, target, mid_measure, final_measure)
```
なので、これを使うと簡単に記述ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322756/368a171b-8691-679b-e3a9-8f3271cf0e12.png)
この問題に解答する回路を作ってみます。

ここでは条件文等は無く、一つ一つシンプルにゲートを作用させていきます。
```Python
def trial(
    circuit: QuantumCircuit,
    target: QuantumRegister,
    controls: QuantumRegister,
    measures: ClassicalRegister,
):
    """Probabilistically perform Rx(theta) on the target, where cos(theta) = 3/5."""

    ####### your code goes here #######
    circuit.h(controls[0])
    circuit.h(controls[1])
    circuit.h(target[0])
    circuit.ccx(controls[0],controls[1],target)
    circuit.s(target[0])
    circuit.ccx(controls[0],controls[1],target)
    circuit.h(controls[0])
    circuit.h(controls[1])
    circuit.h(target)
    circuit.measure(controls[0], measures[0])
    circuit.measure(controls[1], measures[1])    

qc = base.copy_empty_like()
trial(qc, target, controls, mid_measure)
qc.draw("mpl", cregbundle=False)
```
これを実行すると、確かに問いの通り
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322756/05c380c3-c8cd-873f-df41-1dc561ae8f92.png)
が得られます。

#### Lab1-3
次は、こちらの回路を組んでみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322756/fd7259e0-abfc-821f-6f2a-0454ef5e3487.png)
これは、Lab1-1と似た構成のコードになりますが、条件によって作用させるゲートが単一量子ビットへのゲートではなく、レジスターへの制御量子ビットとなります。
```Python
def reset_controls(
    circuit: QuantumCircuit, controls: QuantumRegister, measures: ClassicalRegister
):
    """Reset the control qubits if they are in |1>."""

    ####### your code goes here #######
    with circuit.if_test((measures[0], 1)) as else_:
        # if the condition is satisfied (b0 == 1), then flip the bit back to 0
        circuit.x(controls[0])
    with circuit.if_test((measures[1],1)) as else_:
        circuit.x(controls[1])
        


qc = base.copy_empty_like()
trial(qc, target, controls, mid_measure)
reset_controls(qc, controls, mid_measure)
qc.measure(controls, mid_measure)
qc.draw("mpl", cregbundle=False)
```
これを実行すると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322756/100669ed-f44e-f7e7-e035-6895a29d73fd.png)

となり、この問いもクリアとなります。

#### Lab1-4
ここでは、先ほど作った回路との関係があるので、Quantum Challengeのテキストに従って進めてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322756/3eeb97d0-27f7-6adf-f537-5c72d3a2f347.png)
ターゲット量子ビットをゼロ状態にリセットした後に、先ほど作ったtrial関数を呼び出します。
与えられているコードが少し複雑で、
```Python
# Set the maximum number of trials
max_trials = 2

# Create a clean circuit with the same structure (bits, registers, etc)
# as the initial base we set up.
circuit = base.copy_empty_like()

# The first trial does not need to reset its inputs, since the controls
# are guaranteed to start in the |0> state.
trial(circuit, target, controls, mid_measure)

# Manually add the rest of the trials.  In the future, we will be
# able to use a dynamic `while` loop to do this, but for now, we
# statically add each loop iteration with a manual condition check
# on each one.  This involves more classical synchronizations than
# the while loop, but will suffice for now.
for _ in range(max_trials - 1):
    reset_controls(circuit, controls, mid_measure)
    with circuit.if_test((mid_measure, 0b00)) as else_:
        # This is the success path, but Qiskit can't directly
        # represent a negative condition yet, so we have an
        # empty `true` block in order to use the `else` branch.
        pass
    with else_:
        ####### your code goes here #######
        
        
# We need to measure the control qubits again to ensure we
# get their final results; this is a hardware limitation.
circuit.measure(controls, mid_measure)

# Finally, let's measure our target, to check that we're
# getting the rotation we desired.
circuit.measure(target, final_measure)

circuit.draw("mpl", cregbundle=False)
```
となっていますが、解答としてはとてもシンプルで、
```Python
circuit.x(target[0])
trial(circuit, target, controls, mid_measure)
```
となります。


以上で、Lab1を全て解答できました。
この記事には載っていない、与えられた処理のコードもあるので、皆さん実行する際はTextに従った順番に計算してくださいね。

次回、Lab2もご紹介したいと思います！