前のレッスンでは、QiskitのStatevectorクラスとOperatorクラスを初めて確認し、単一量子ビットに対する操作と測定のシミュレーションに使用しました。
このセクションでは、これらのクラスを使って複数量子ビットの動作を調べます。
!pip install -q numpy qiskit
from qiskit import __version__
print(__version__)
まず、StatevectorクラスとOperatorクラス、そしてNumPyの平方根関数をインポートします。
以降、各レッスンでは原則として必要なインポートをすべて最初にまとめて行います。
from qiskit.quantum_info import Statevector, Operator
from numpy import sqrt
テンソル積
Statevectorクラスにはtensorメソッドがあり、引数として渡した別のStatevectorとのテンソル積を返します。
引数は右側のテンソル因子として解釈されます。
たとえば、以下では ∣0⟩ と ∣1⟩ を表す2つの状態ベクトルを作成し、tensorメソッドを使って新しいベクトル ∣ψ⟩=∣0⟩⊗∣1⟩ を作成しています。
ここでは、∣0⟩ と ∣1⟩ の状態を自分で定義する代わりに、from_labelメソッドを使用していることに注目してください。
zero = Statevector.from_label("0")
one = Statevector.from_label("1")
psi = zero.tensor(one)
display(psi.draw("latex"))
∣01⟩
その他に使用できるラベルとして、プラス状態とマイナス状態には "+" と "-"、そして
∣+i⟩=21∣0⟩+2i∣1⟩and∣−i⟩=21∣0⟩−2i∣1⟩.
の状態には "r" と "l"("right"(右)と "left"(左)の略)があります。
ここでの「右」「左」は量子力学的スピンの文脈から来ており、実験でスピンの成分が左または右を向く場合に用いられるものです。複数量子ビット系における右端・左端の量子ビットを指しているわけではありません。以下は ∣+⟩ と ∣−i⟩ のテンソル積の例です。
plus = Statevector.from_label("+")
minus_i = Statevector.from_label("l")
phi = plus.tensor(minus_i)
display(phi.draw("latex"))
21∣00⟩−2i∣01⟩+21∣10⟩−2i∣11⟩
テンソル積には^演算子を使う方法もあり、当然ながら同じ結果が得られます。
display((plus ^ minus_i).draw("latex"))
21∣00⟩−2i∣01⟩+21∣10⟩−2i∣11⟩
次の例で示すように、Operatorクラスにもtensorメソッド(およびfrom_labelメソッド)があります。
H = Operator.from_label("H")
Id = Operator.from_label("I")
X = Operator.from_label("X")
display(H.tensor(Id).draw("latex"))
display(H.tensor(Id).tensor(X).draw("latex"))
220220022022220−2200220−22
0220002200220002200000022000220022000220022000−220022000−2200000022000−220022000−220
ベクトルの場合と同様に、^演算子も同等の結果を返します。
display((H ^ Id ^ X).draw("latex"))
0220002200220002200000022000220022000220022000−220022000−2200000022000−220022000−220
前のレッスンで単一系について見たのと同様に、複合状態は複合演算子を使って時間発展させることができます。
たとえば、以下のコードは(上ですでに定義した)∣ϕ⟩=∣+⟩⊗∣−i⟩ に対して状態 (H⊗I)∣ϕ⟩ を計算します。
display(phi.evolve(H ^ Id).draw("latex"))
22∣00⟩−22i∣01⟩
以下のコードは CX 演算子を定義し、∣ψ⟩=∣+⟩⊗∣0⟩ に対して CX∣ψ⟩ を計算します。ここでは左側の量子ビットが制御、右側の量子ビットがターゲットとなる CX 演算子です。結果はベル状態 ∣ϕ+⟩ となります。
CX = Operator([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
psi = plus.tensor(zero)
display(psi.evolve(CX).draw("latex"))
22∣00⟩+22∣11⟩
部分測定
前のレッスンでは、量子状態ベクトルの測定をシミュレートするためにmeasureメソッドを使用しました。
このメソッドは、シミュレートされた測定結果と、その測定後の新しいStatevectorの2つの値を返します。
デフォルトでは、measureは状態ベクトル内のすべての量子ビットを測定します。
代わりに整数のリストを引数として渡すと、指定した量子ビットのインデックスのみが測定されます。
これを実証するために、以下のコードで状態
∣w⟩=3∣001⟩+∣010⟩+∣100⟩
を作成し、右端の量子ビットである量子ビット番号0を測定します。
(Qiskitでは量子ビットに0から始まる番号を右から左の順に付けます。この番号付け規則については次のレッスンで改めて説明します。)
w = Statevector([0, 1, 1, 0, 1, 0, 0, 0] / sqrt(3))
display(w.draw("latex"))
result, state = w.measure([0])
print(f"Measured: {result}\nState after measurement:")
display(state.draw("latex"))
result, state = w.measure([0, 1])
print(f"Measured: {result}\nState after measurement:")
display(state.draw("latex"))
33∣001⟩+33∣010⟩+33∣100⟩
Measured: 0
State after measurement:
22∣010⟩+22∣100⟩
Measured: 00
State after measurement:
∣100⟩