逆演算 (1) - らんだむな記憶 の続きとして、textbook で扱われているサンプルについて眺める。textbook そのままであるが、一部気になったので補足を追加する。
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister from qiskit import execute, Aer from qiskit.visualization import plot_histogram input_bit = QuantumRegister(1, 'input') output_bit = QuantumRegister(1, 'output') garbage_bit = QuantumRegister(1, 'garbage') Uf = QuantumCircuit(input_bit, output_bit, garbage_bit) Uf.cx(input_bit[0], output_bit[0]) Vf = QuantumCircuit(input_bit, output_bit, garbage_bit) Vf.cx(input_bit[0], garbage_bit[0]) Vf.cx(input_bit[0], output_bit[0]) final_output_bit = QuantumRegister(1, 'final-output') copy = QuantumCircuit(output_bit, final_output_bit) copy.cx(output_bit, final_output_bit) qbits = (input_bit, output_bit, garbage_bit, final_output_bit) clbits = ClassicalRegister(len(qbits), 'c') qc = QuantumCircuit(*qbits, clbits) qc.h(0) qc.barrier() qc = qc.compose(Vf.inverse()) qc = qc.compose(copy, qubits=[1, 3]) qc = qc.compose(Vf) qc.barrier() for i in range(qc.num_qubits): qc.measure(i, i) qc.draw('mpl')
で回路を作って可視化すると:
このような感じに。これを測定すると、入力を $\frac{1}{\sqrt{2}}(\ket{0} + \ket{1})$ で初期化したので、$\ket{q_0} = \ket{0}$ の時は $\ket{f(x)} = \ket{0}$ が、$\ket{q_0} = \ket{1}$ の時は $\ket{f(x)} = \ket{1}$ が 50% ずつ観測されるはずである。つまり、$\ket{0000}$ と $\ket{1001}$ が 50% ずつ観測されるはずである。
backend = Aer.get_backend('qasm_simulator') shots = 1042 results = execute(qc, backend=backend, shots=shots).result() answer = results.get_counts() plot_histogram(answer)
を実行すると:
ということで期待通りの結果となる。
・・・ただ、textbook の内容だと回路の構成順序がコード的には違うのではないだろうか・・・。(実質回路も等価ではあるのだが・・・) 操作として $V_f^\dagger U_{2,4}^{cp} V_f$ を適用する場合、見た目の式の順序とコードの適用順は逆になると思われる。
qc = qc.compose(Vf) qc = qc.compose(copy, qubits=[1, 3]) qc = qc.compose(Vf.inverse())
だと思うのだが、この場合は回路図は以下のようになるだけで、測定と観測結果は特に変化はしない: