らんだむな記憶

blogというものを体験してみようか!的なー

Qiskit (21) ― Deutsch-Jozsa アルゴリズム

Deutsch-Jozsa アルゴリズムのコードではゲートの用意から測定までが入り混じったコードになっていて、コードを実行しても「ふぅん・・・」という感想になってしまったので、少し書き換えて barrier を挟んでみた:

n = 3

# オラクル f の定義
oracle = "b"

if oracle == "c":
    c = np.random.randint(2)

Circuit = QuantumCircuit(n+1, n)

# q_3 を |1> で初期化。
# Circuit.x(n)
initial_state = [0, 1]
Circuit.initialize(initial_state, n)

for qubit in range(n+1):
    Circuit.h(qubit)

Circuit.barrier()    

# ユニタリゲート U_f の具体的な作成
def operate_Uf_to_circuit(Circuit):
    if oracle == "c":
        if c == 1:
            Circuit.x(n)
        else:
            Circuit.id(n)
    else:
        for ctr in range(n):
            Circuit.cx(ctr, n)
    Circuit.barrier()

# 測定者はこのゲート U_f を使ってオラクルに問い合わせができる。
# ここからが f 決定のための回路

# U_f を用いて、1 回の測定で f を決定できる仕組みを回路に適用
def apply_solver_to_circuit(Circuit):
    operate_Uf_to_circuit(Circuit)
    for qubit in range(n):
        Circuit.h(qubit)
    Circuit.barrier()
    for i in range(n):
        Circuit.measure(i, i)
apply_solver_to_circuit(Circuit)

これを可視化すると

定数関数

f:id:derwind:20220123210258p:plain

バランス関数

f:id:derwind:20220123210313p:plain

となる。
左から 2 番目の区画がゲート $U_f$ の部分であり、これの適用を上記では operate_Uf_to_circuit に担わせている。3 番目の区画では $\frac{1}{\sqrt{2}}(\ket{0} - \ket{1})$ が無視され、以降 q_0, q_1, q_2 のみが興味の対象となっている。

今回実装が丸見えであるが、実装が未知の operate_Uf_to_circuit が与えられたという前提で、apply_solver_to_circuit を実装すると 1 回の測定でオラクル $f$ が定数関数かバランス関数かを決定できる。古典アルゴリズムなら $2^3/2 + 1 = 5$ 通りの組み合わせで $f(x)$ の出力を確認する必要があるので、この差は劇的である・・・ということのようだ。

これで書籍 p.118 までが完了となる。