メインコンテンツへスキップ
このプロジェクトはベータ版です。バグを見つけましたか?GitHub Issueを開く。質問やアイデアがありますか?Discussionsで質問する — フィードバックをお待ちしています!
このページの翻訳品質はいかがですか?

Qiskitによる実装

前のレッスンでは、QiskitのStatevectorクラスとOperatorクラスを初めて確認し、単一量子ビットに対する操作と測定のシミュレーションに使用しました。 このセクションでは、これらのクラスを使って複数量子ビットの動作を調べます。

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit import __version__

print(__version__)
2.1.1

まず、StatevectorクラスとOperatorクラス、そしてNumPyの平方根関数をインポートします。 以降、各レッスンでは原則として必要なインポートをすべて最初にまとめて行います。

from qiskit.quantum_info import Statevector, Operator
from numpy import sqrt

テンソル積​

Statevector クラスには tensor メソッドがあり、その Statevector と、引数として与えられた別の Statevector とのテンソル積を返します。 引数は右側のテンソル因子として解釈されます。

例えば、以下では∣0⟩\vert 0\rangleと∣1⟩\vert 1\rangleを表す2つの状態ベクトルを作成し、tensorメソッドを使って新しいベクトル∣ψ⟩=∣0⟩⊗∣1⟩\vert \psi\rangle = \vert 0\rangle \otimes \vert 1\rangleを作成します。 ここでは、状態∣0⟩\vert 0\rangleと∣1⟩\vert 1\rangleを自分で定義するのではなく、from_labelメソッドを使用していることに注目してください。

zero = Statevector.from_label("0")
one = Statevector.from_label("1")
psi = zero.tensor(one)
display(psi.draw("latex"))

∣01⟩ |01\rangle

その他に使用できるラベルには、プラス状態とマイナス状態を表す「+」と「-」、そして次の状態を表す(「right」と「left」の略の)「r」と「l」があります

∣+i⟩=12∣0⟩+i2∣1⟩and∣−i⟩=12∣0⟩−i2∣1⟩.\vert {+i} \rangle = \frac{1}{\sqrt{2}} \vert 0 \rangle + \frac{i}{\sqrt{2}} \vert 1 \rangle \qquad\text{and}\qquad \vert {-i} \rangle = \frac{1}{\sqrt{2}} \vert 0 \rangle - \frac{i}{\sqrt{2}} \vert 1 \rangle.

ここでの「+」「-」や「右」「左」は量子力学的スピンの文脈から来ており、実験でスピンの成分が左または右を向く場合に用いられるものです。複数量子ビット系における右端・左端の量子ビットを指しているわけではありません。以下は ∣+⟩\vert {+} \rangle と ∣−i⟩\vert {-i} \rangle のテンソル積の例です。

plus = Statevector.from_label("+")
minus_i = Statevector.from_label("l")
phi = plus.tensor(minus_i)
display(phi.draw("latex"))

12∣00⟩−i2∣01⟩+12∣10⟩−i2∣11⟩\frac{1}{2} |00\rangle- \frac{i}{2} |01\rangle+\frac{1}{2} |10\rangle- \frac{i}{2} |11\rangle

テンソル積には^演算子を使う方法もあり、当然ながら同じ結果が得られます。

display((plus ^ minus_i).draw("latex"))

12∣00⟩−i2∣01⟩+12∣10⟩−i2∣11⟩\frac{1}{2} |00\rangle- \frac{i}{2} |01\rangle+\frac{1}{2} |10\rangle- \frac{i}{2} |11\rangle

次の例で示すように、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] \begin{bmatrix} \frac{\sqrt{2}}{2} & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & \frac{\sqrt{2}}{2} \\ \frac{\sqrt{2}}{2} & 0 & - \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & - \frac{\sqrt{2}}{2} \\ \end{bmatrix} [0220002200220002200000022000220022000220022000−220022000−2200000022000−220022000−220] \begin{bmatrix} 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 \\ \end{bmatrix}

ベクトルの場合と同様に、^演算子も同等の結果を返します。

display((H ^ Id ^ X).draw("latex"))
[0220002200220002200000022000220022000220022000−220022000−2200000022000−220022000−220] \begin{bmatrix} 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 \\ \end{bmatrix}

前のレッスンで単一系について見たのと同様に、複合状態は、予想どおり複合演算子を使って時間発展させることができます。 たとえば、以下のコードは(上ですでに定義した)∣ϕ⟩=∣+⟩⊗∣−i⟩\vert\phi\rangle = \vert + \rangle \otimes \vert {-i}\rangle に対して状態 (H⊗I)∣ϕ⟩(H\otimes I)\vert\phi\rangle を計算します。

display(phi.evolve(H ^ Id).draw("latex"))

22∣00⟩−2i2∣01⟩\frac{\sqrt{2}}{2} |00\rangle- \frac{\sqrt{2} i}{2} |01\rangle

以下のコードは CXCX 演算子を定義し、∣ψ⟩=∣+⟩⊗∣0⟩\vert\psi\rangle = \vert + \rangle \otimes \vert 0 \rangle に対して CX∣ψ⟩CX \vert\psi\rangle を計算します。ここでは左側の量子ビットが制御、右側の量子ビットがターゲットとなる CXCX 演算子です。結果はベル状態 ∣ϕ+⟩\vert\phi^{+}\rangle となります。

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⟩\frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |11\rangle

部分測定​

前のレッスンでは、量子状態ベクトルの測定をシミュレートするためにmeasureメソッドを使用しました。 このメソッドは、シミュレートされた測定結果と、その測定後の新しいStatevectorの2つの値を返します。

デフォルトでは、measureは状態ベクトル内のすべての量子ビットを測定します。 代わりに整数のリストを引数として渡すと、指定した量子ビットのインデックスのみが測定されます。 これを実証するために、以下のコードで状態

∣w⟩=∣001⟩+∣010⟩+∣100⟩3\vert w\rangle = \frac{\vert 001\rangle + \vert 010\rangle + \vert 100\rangle}{\sqrt{3}}

を作成し、右端の量子ビットである量子ビット番号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⟩\frac{\sqrt{3}}{3} |001\rangle+\frac{\sqrt{3}}{3} |010\rangle+\frac{\sqrt{3}}{3} |100\rangle

Measured: 0
State after measurement:

22∣010⟩+22∣100⟩\frac{\sqrt{2}}{2} |010\rangle+\frac{\sqrt{2}}{2} |100\rangle

Measured: 00
State after measurement:

∣100⟩ |100\rangle