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)
これを可視化すると
定数関数
バランス関数
となる。
左から 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 までが完了となる。