Qulacs使ってみた報告
Google Colaboratory で Qulacs使ってみた報告.
Qulacsとは
高速な量子回路シミュレータ.Python・C・C++に対応.
チュートリアル
親切な解説(日本語)がある.とはいえこの記事でも逐次説明する.
インストール
以下のコマンドでQulacsをColab上でインストールできる.
!pip install qulacs
## Google Colaboratory/(Linux or Mac)のjupyter notebook環境の場合にのみ実行してください。
## Qulacsのエラーが正常に出力されるようになります。
!pip3 install wurlitzer
量子フーリエ変換回路
量子フーリエ変換の回路は以下の図で書かれる.
ここで
量子フーリエ変換の回路は2ビット目以降に対しては QuantumCircuit
から QuantumCircuit
を作る機能は用意されていないようなので,以下のようにする.
ゲート関数
ゲートを作成する関数を作り,後のゲート作成を自動化する.
from qulacs import QuantumState
from qulacs.gate import DenseMatrix
from cmath import exp
import math
def gate_R(param,target,control):
gate = DenseMatrix(target, [[1,0],[0,exp((0 + 1j) * math.pi /2**(param-1))]])
gate.add_control_qubit(control,1)
return gate
重要ポイントは以下の通り.
- 行列で表されるゲートを作るには
DenseMatrix(target,matrix)
を使う.-
target
は対象の制御対象の量子ビットの番号.(番号は0から始まる) -
matrix
はゲートの行列.
-
- コントロールビットを持っている場合は
.add_control_qubit(control,X)
を用いて素の(コントロールビットを持たない)ゲートに追加する.-
control
は制御ビットの番号. -
X
は制御ビットがどちらのときに適用するか(X=1
なら 1のときに作用する).
-
ゲート追加関数
ゲート追加関数 add_n_fourier(circuit,circuit_size,target_number)
は,
- 量子回路
circuit
- 回路の量子ビット数
circuit_size
- 現在追加対象の量子ビット
target_number
以上を元に circuit
に n 次元フーリエ変換回路を付加する関数.
ちなみに,1次元フーリエ変換回路は H
ゲートを作用させるだけである.
def add_n_fourier(circuit,circuit_size,target_number):
circuit.add_H_gate(target_number);
if target_number == circuit_size - 1 :
return
for i in range(circuit_size - target_number - 1):
circuit.add_gate(gate_R(i+2,target_number,i+target_number+1))
add_n_fourier(circuit,circuit_size,target_number+1)
実際に使うときには target_number
には 0 を入れる.
動作確認
以下のコードで正しく動いているかチェックする.テストコードが汚すぎる・・・
from qulacs import QuantumCircuit
n = 2
circuit = QuantumCircuit(n)
add_n_fourier(circuit, n, 0)
state0 = QuantumState(n)
state1 = QuantumState(n)
state2 = QuantumState(n)
state3 = QuantumState(n)
state0.set_computational_basis(0b00)
state1.set_computational_basis(0b01)
state2.set_computational_basis(0b10)
state3.set_computational_basis(0b11)
print(state0.get_vector())
print(state1.get_vector())
print(state2.get_vector())
print(state3.get_vector())
circuit.update_quantum_state(state0)
circuit.update_quantum_state(state1)
circuit.update_quantum_state(state2)
circuit.update_quantum_state(state3)
print("実行後")
print(state0.get_vector())
print(state1.get_vector())
print(state2.get_vector())
print(state3.get_vector())
重要ポイントは以下の通り.
-
QuantumCircuit(n)
でn
量子ビットの量子回路を作る. -
QuantumState(n)
でn
量子ビットの量子状態(ベクトル)を作る. -
state.set_computational_basis(0b00)
で量子状態state
を にする.\ket{00} -
state.get_vector()
で量子状態state
をベクトルとして表示する. -
circuit.update_quantum_state(state)
で量子状態state
に量子回路circuit
を適用する.
この実行結果が以下の通り.上が通過前,下が回路通過後の状態である.
[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
[0.+0.j 1.+0.j 0.+0.j 0.+0.j]
[0.+0.j 0.+0.j 1.+0.j 0.+0.j]
[0.+0.j 0.+0.j 0.+0.j 1.+0.j]
実行後
[0.5+0.j 0.5+0.j 0.5+0.j 0.5+0.j]
[ 0.5+0.j -0.5+0.j 0.5+0.j -0.5+0.j]
[ 5.000000e-01+0.j 3.061617e-17+0.5j -5.000000e-01+0.j
-3.061617e-17-0.5j]
[ 5.000000e-01+0.j -3.061617e-17-0.5j -5.000000e-01+0.j
3.061617e-17+0.5j]
e-17
は
array0 = [1,0,0,0]
array1 = [0,1,0,0]
array2 = [0,0,1,0]
array3 = [0,0,0,1]
def calculator(array,k):
sum = 0
sum += array[0] * exp(-2 * math.pi * (0+1j) * k * 0/4)
sum += array[1] * exp(-2 * math.pi * (0+1j) * k * 1/4)
sum += array[2] * exp(-2 * math.pi * (0+1j) * k * 2/4)
sum += array[3] * exp(-2 * math.pi * (0+1j) * k * 3/4)
return sum/2
sum00,sum01,sum02,sum03 = calculator(array0,0) , calculator(array0,1),calculator(array0,2),calculator(array0,3)
sum10,sum11,sum12,sum13 = calculator(array1,0) , calculator(array1,1),calculator(array1,2),calculator(array1,3)
sum20,sum21,sum22,sum23 = calculator(array2,0) , calculator(array2,1),calculator(array2,2),calculator(array2,3)
sum30,sum31,sum32,sum33 = calculator(array3,0) , calculator(array3,1),calculator(array3,2),calculator(array3,3)
print(sum00,sum01,sum02,sum03)
print(sum10,sum11,sum12,sum13)
print(sum20,sum21,sum22,sum33)
print(sum30,sum31,sum32,sum33)
これの実行結果は以下の通り.これはフーリエ変換後の値しかprintしていない.
(0.5+0j) (0.5+0j) (0.5+0j) (0.5+0j)
(0.5+0j) (3.061616997868383e-17-0.5j) (-0.5-6.123233995736766e-17j) (-9.184850993605148e-17+0.5j)
(0.5+0j) (-0.5-6.123233995736766e-17j) (0.5+1.2246467991473532e-16j) (2.755455298081545e-16-0.5j)
(0.5+0j) (-9.184850993605148e-17+0.5j) (-0.5-1.8369701987210297e-16j) (2.755455298081545e-16-0.5j)
こっちも端数 e-16
とか e-17
を実質
結論
Qulacsを使って
Discussion