解説
はじめに、∣x⟩→∣(x−1)mod2n⟩ の逆操作である ∣x⟩→∣(x+1)mod2n⟩ という操作について考えます。
あらかじめ、x を長さ n のビット列 x0x1⋯xn−1 を用いて表現することとします。
∣x⟩=∣x0x1⋯xn−1⟩n
この表現を元に、∣x⟩→∣(x+1)mod2n⟩ という操作は以下のように言い換えることができます。
- 下位ビットから順に 1 が連続する部分を全て 0 に変換し、はじめて 0 が出てくるビットを 1 に反転させる。
- 具体的には、「 x0=x1=⋯=xi−1=1,xi=0 」となる i (1≤i<n) を探し、x0,x1,⋯,xi−1 を 0 に反転させ、xi を 1 に反転させます。
ただし、「 x0=x1=⋯=xn−1=1 」となる時は、x0,x1,⋯,xn−1 を 0 に反転させ、「 x0=x1=⋯=xn−1=0 」となる時は、x0 を 1 に反転させます。
以下の n=3 の例をみてみましょう。
ここで、入力状態として ∣110⟩ が与えられたとします。
まず、「1,2 番目の量子ビットを制御ビット、3 番目の量子ビットを標的ビットとする複数制御 X ゲート1」によって、以下の状態遷移が成り立ちます。
∣110⟩MCX((0,1),2)∣111⟩
次に、「1 番目の量子ビットを制御ビット、2 番目の量子ビットを標的ビットとする制御 X ゲート」によって、以下の状態遷移が成り立ちます。
∣111⟩CX(0,1)∣101⟩
最後に、X ゲートによって、以下の状態遷移が成り立ちます。
∣101⟩X(0)∣001⟩
結果として、∣110⟩→∣001⟩ という操作を実現できていることが確認できます。
以上の操作を一般化すると、∣x⟩→∣(x+1)mod2n⟩ という操作を実現することができ、コードとしては以下のようになります。
from qiskit import QuantumCircuit
def solve(n: int) -> QuantumCircuit:
qc = QuantumCircuit(n)
for i in reversed(range(1, n)):
qc.mcx(list(range(i)), i)
qc.x(0)
return qc
そして、それらのゲートを逆順に適用していくことで ∣x⟩→∣(x−1)mod2n⟩ という操作を実現できるため、結果としてこの問題を解くことができます。
解答例
解答例は以下の通りです。
from qiskit import QuantumCircuit
def solve(n: int) -> QuantumCircuit:
qc = QuantumCircuit(n)
qc.x(0)
for i in range(1, n):
qc.mcx(list(range(i)), i)
return qc
次のように、∣x⟩→∣(x+1)mod2n⟩ に対して inverse メソッドを使って記述することもできます。
from qiskit import QuantumCircuit
def solve(n: int) -> QuantumCircuit:
qc = QuantumCircuit(n)
for i in reversed(range(1, n)):
qc.mcx(list(range(i)), i)
qc.x(0)
return qc.inverse()
発展
整数 a を 20,21,… と 2n−20,2n−21,… の和に分解すると、∣x⟩→∣x+a(mod2n)⟩ は本問題のアルゴリズムを高々 ⌈2log2(a)+1⌉ 回適用して実現できます。