# Python 教材¶

## 量子状態¶

### 量子状態の生成¶

from qulacs import QuantumState

# 2-qubitの状態を生成
n = 2
state = QuantumState(n)
print(state)

 *** Quantum State ***
* Qubit Count : 2
* Dimension   : 4
* State vector :
(1,0)
(0,0)
(0,0)
(0,0)


### 量子状態の初期化¶

from qulacs import QuantumState

n = 2
state = QuantumState(n)

# |00>に初期化
state.set_zero_state()

# 基底を二進数と見た時の整数値を入れて、その状態に初期化
state.set_computational_basis(1)
print(state)

# シードを指定してランダムな初期状態を生成
# (シードを省略した場合は時刻を用いてシードを決定します。)
seed = 0
state.set_Haar_random_state(seed)
print(state)

 *** Quantum State ***
* Qubit Count : 2
* Dimension   : 4
* State vector :
(0,0)
(1,0)
(0,0)
(0,0)

*** Quantum State ***
* Qubit Count : 2
* Dimension   : 4
* State vector :
(0.0531326,0.551481)
(0.382474,0.10121)
(-0.499658,-0.0931227)
(0.474029,-0.231262)


### 状態ベクトルの取得と設定¶

import numpy as np
from qulacs import QuantumState

n = 2
state = QuantumState(n)

# 状態ベクトルを取得
vec = state.get_vector()
print(type(vec), vec.dtype)
print(vec)

# 状態ベクトルを設定
myvec = np.array([0.5,0.5,0.5,0.5])
print(state)

<class 'numpy.ndarray'> complex128
[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
*** Quantum State ***
* Qubit Count : 2
* Dimension   : 4
* State vector :
(0.5,0)
(0.5,0)
(0.5,0)
(0.5,0)


### 量子状態に関する情報の計算¶

from qulacs import QuantumState

n = 5
state = QuantumState(n)
state.set_Haar_random_state(0)

# 指定した添え字のqubitをZ基底で測定して0を得る確率の計算
index = 3
zero_probability = state.get_zero_probability(index)
print("prob_meas_3rd : ",zero_probability)

prob_meas_3rd :  0.6015549753834679


import numpy as np
from qulacs import QuantumState

n = 2
state = QuantumState(n)
data = state.sampling(10)
print(data)
print([format(value, "b").zfill(2) for value in data]) # 二進数表示

[0, 3, 3, 3, 3, 0, 2, 3, 0, 3]
['00', '11', '11', '11', '11', '00', '10', '11', '00', '11']


### 量子状態の内積¶

from qulacs import QuantumState
from qulacs.state import inner_product

n = 5
state_bra = QuantumState(n)
state_ket = QuantumState(n)
state_bra.set_Haar_random_state()
state_ket.set_computational_basis(0)

# 内積値の計算
value = inner_product(state_bra, state_ket)
print(value)

(0.1265907720817918+0.10220657039660046j)


## 量子ゲート¶

### 量子ゲートの生成¶

from qulacs.gate import X

target_index = 1
x_gate = X(target_index)
print(x_gate)

 *** gate info ***
* gate name : X
* target    :
1 : commute X
* control   :
* Pauli     : yes
* Clifford  : yes
* Gaussian  : no
* Parametric: no
* Diagonal  : no


### 量子ゲートの作用¶

from qulacs import QuantumState
from qulacs.gate import X

n = 2
state = QuantumState(n)
print(state)

index = 1
x_gate = X(index)
x_gate.update_quantum_state(state)
print(state)

 *** Quantum State ***
* Qubit Count : 2
* Dimension   : 4
* State vector :
(1,0)
(0,0)
(0,0)
(0,0)

*** Quantum State ***
* Qubit Count : 2
* Dimension   : 4
* State vector :
(0,0)
(0,0)
(1,0)
(0,0)


### 様々な量子ゲート¶

import numpy as np

# パウリゲート、アダマールゲート、Tゲート
from qulacs.gate import X, Y, Z, H, T
target = 2
x_gate = X(target)
y_gate = Y(target)
z_gate = Z(target)
h_gate = H(target)
t_gate = T(target)

# パウリ回転ゲート
from qulacs.gate import RX, RY, RZ
angle = np.pi / 4.0
rx_gate = RX(target, angle)
ry_gate = RY(target, angle)
rz_gate = RZ(target, angle)

# CNOT, CZ, SWAPゲート
from qulacs.gate import CNOT, CZ, SWAP
control = 1
target2 = 1
cnot_gate = CNOT(control, target)
cz_gate = CZ(control, target)
swap_gate = SWAP(target, target2)


### 一般的な量子ゲート¶

from qulacs.gate import DenseMatrix

gate = DenseMatrix(1, [[0,1],[1,0]])
print(gate)

 *** gate info ***
* gate name : DenseMatrix
* target    :
1 : commute
* control   :
* Pauli     : no
* Clifford  : no
* Gaussian  : no
* Parametric: no
* Diagonal  : no
* Matrix
(0,0) (1,0)
(1,0) (0,0)


２量子ビット以上の大きさのゲートを作るには、一つ目の引数に対象となる添え字のリストを、二つ目に行列を与えます。n量子ビットゲートを作るとき、行列の大きさは \f$2^n\f$ 次元でなければなりません。

from qulacs.gate import DenseMatrix

gate = DenseMatrix([0,1], [[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0]])
print(gate)

 *** gate info ***
* gate name : DenseMatrix
* target    :
5 : commute
3 : commute
* control   :
* Pauli     : no
* Clifford  : no
* Gaussian  : no
* Parametric: no
* Diagonal  : no
* Matrix
(0,0) (1,0) (0,0) (0,0)
(1,0) (0,0) (0,0) (0,0)
(0,0) (0,0) (0,0) (1,0)
(0,0) (0,0) (1,0) (0,0)


なお、ゲート行列の列や行を数えるときに下位ビットとなる添え字は、ゲート生成時に与える添え字の順番に対応するため、上記の例で作用する添え字のリストが[0,1][1,0]では意味が異なることに注意してください。以下は添え字を入れ替えた時の違いを表しています。

from qulacs import QuanutmState
from qulacs.gate import DenseMatrix

gate1 = DenseMatrix([0,1], [[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0]])
gate2 = DenseMatrix([1,0], [[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0]])
state = QuantumState(2)

state.set_zero_state()
gate1.update_quantum_state(state)
print(state.get_vector())

state.set_zero_state()
gate2.update_quantum_state(state)
print(state.get_vector())

[0.+0.j 1.+0.j 0.+0.j 0.+0.j]
[0.+0.j 0.+0.j 1.+0.j 0.+0.j]


### コントロールビットの追加¶

from qulacs.gate import DenseMatrix

gate = DenseMatrix(1, [[0,1],[1,0]])
print(gate)

 *** gate info ***
* gate name : DenseMatrix
* target    :
1 : commute
* control   :
3 : value 1
* Pauli     : no
* Clifford  : no
* Gaussian  : no
* Parametric: no
* Diagonal  : no
* Matrix
(0,0) (1,0)
(1,0) (0,0)


### 一般的な行列ゲートへの変換¶

Xゲートのような名前の付いた特殊なゲートは一般的な行列ゲートより高速に量子状態を更新できる一方、add_control_qubitのような加工が行えません。特殊なゲートを元にしてゲートを加工するには、to_matrix_gate関数を用いて特殊なゲートを一般的なゲートに変換します。

from qulacs.gate import X, to_matrix_gate

gate = X(1)
print(gate)
gate = to_matrix_gate(gate)
print(gate)

 *** gate info ***
* gate name : X
* target    :
1 : commute X
* control   :
* Pauli     : yes
* Clifford  : yes
* Gaussian  : no
* Parametric: no
* Diagonal  : no

*** gate info ***
* gate name : DenseMatrix
* target    :
1 : commute X
* control   :
* Pauli     : no
* Clifford  : no
* Gaussian  : no
* Parametric: no
* Diagonal  : no
* Matrix
(0,0) (1,0)
(1,0) (0,0)


### 量子ゲートのゲート行列の取得¶

from qulacs.gate import H, CNOT

h_gate = H(2)
matrix = h_gate.get_matrix()
print(matrix)
cnot_gate = CNOT(1,2)
matrix = cnot_gate.get_matrix()
print(matrix)

[[ 0.70710678+0.j  0.70710678+0.j]
[ 0.70710678+0.j -0.70710678+0.j]]
[[0.+0.j 1.+0.j]
[1.+0.j 0.+0.j]]


## 量子回路¶

### 量子回路の生成と構成¶

from qulacs import QuantumCircuit

n = 5
circuit = QuantumCircuit(n)

from qulacs.gate import X
gate = X(2)

print(circuit)

*** Quantum Circuit Info ***
# of qubit: 5
# of step : 2
# of gate : 3
# of 1 qubit gate: 3
Clifford  : yes
Gaussian  : no


### 量子回路の作用¶

from qulacs import QuantumCircuit

n=3
circuit = QuantumCircuit(n)

from qulacs import QuantumState
state = QuantumState(n)
circuit.update_quantum_state(state)
print(state)

 *** Quantum State ***
* Qubit Count : 3
* Dimension   : 8
* State vector :
(0.706223,0)
(0,0)
(0.706223,0)
(0,0)
(0,0.0353406)
(0,0)
(0,0.0353406)
(0,0)