不確定性を探る
このQiskit in Classroomsモジュールでは、学生は以下のパッケージがインストールされた動作するPython環境を用意する必要があります:
qiskitv2.1.0以降qiskit-ibm-runtimev0.40.1以降qiskit-aerv0.17.0以降qiskit.visualizationnumpypylatexenc
上記パッケージのセットアップとインストールについては、Qiskitのインストールガイドを参照してください。 実際の量子コンピューター上でジョブを実行するには、IBM Cloudアカウントのセットアップガイドの手順に従い、IBM Quantum®のアカウントを作成する必要があります。
このモジュールはテスト済みで、QPU時間を8分使用しました。これはあくまでも推定値です。実際の使用量は異なる場合があります。時間のかかる計算が2つあり、ヘッダーコメントでそのように明記されています。QPU時間が不足している学生はシミュレーターで実行できます。それらを除いた場合、モジュールが必要とするQPU時間は約30秒のみです。
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-aer qiskit-ibm-runtime
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'
以下でDr. Katie McCormickによるモジュールのウォークスルー動画をご覧いただくか、こちらからYouTubeで参照してください。
はじめに
不確定性原理については、物理の授業以外でも耳にしたことがあるでしょう。不確定性についてよく知られた口語的な言い換えとして「何かを観測すると、それに影響を与えてしまう」というものがあります。それは確かに真実です。しかし不確定性をより物理的に表現すると、ある種の物理的観測量には非両立性(incompatibility)があり、それらを同時に任意の精度で知ることができないということです。多くの学生が最初に出会う非両立な変数のペアは と 、すなわち 軸と呼ばれる一つの軸に沿った位置と、その方向の線形運動量です。これらの変数に対する不確定性の制約は次のように書かれます: ここで は「 の不確定性」と呼ばれ、統計学における標準偏差と同じ定義を持ち、次のように定義できます: も同様に定義されます。 ここでは、この不確定性関係を導出しません。古典的な波動の理解と整合していることを指摘するにとどめます。すなわち、真に完全な1つの周波数 と波長 を持つ波は、完全な正弦波として永遠に続きます。量子力学的には、ド・ブロイの仮説 によれば、これは運動量を完全に知ることに対応します。しかし波のような粒子がどこにいるか知るためには、それを記述する波が空間的に非常に鋭いピークを持つ形(例えば非常に幅の狭いガウス関数)にならなければなりません。そのような鋭いピークを持つ波動関数を含む任意の連続関数は、異なる波長を持つ正弦関数のフーリエ級数で表現できることは知られています。しかし波動関数がより鋭いピークになる(位置がより正確に知られる)につれて、フーリエ級数にはより多くの項が必要になります。つまりより多くの波長の混合(量子力学的には、より多くの運動量の値)が必要になります。
より簡潔に述べると:運動量が確定した状態(空間的に完全な正弦波)は位置が非常に不確定です。位置が確定した状態(ディラックのデルタ分布のような)は運動量が非常に不確定です。
このような非両立性を示す変数は他にもあります。例えば、粒子のスピンはある軸に沿った射影が確定していても、直交する軸への射影については何も分からない場合があります。例えば状態 (Qubitまたはスピン-1/2粒子の場合)は 軸に沿った射影が確定しています(Qubitの文脈では1、スピン-1/2粒子の文脈では )。しかしこの状態は、 軸への射影が確定した2つの状態の重ね合わせとして書くことができます: または同等に は への射影が確定しており、 も同様です。したがって、状態の 軸への射影を指定すると、 軸への射影は分かりません。また 軸への射影を指定すると、 への射影は分かりません。スピンとQubitの文脈でこれを議論する際には細かな違いがありますが、一般的に言えば、パウリ行列の固有状態には面白い関係があり、それを探ることができます。 このレッスン全体を通して、これらの非両立な変数の不確定性に対する直感を実験的に確認し、IBM®量子コンピューター上で不確定性関係が成立することを検証します。
直感の簡単な確認
この最初の実験と以降のモジュール全体を通して、「Qiskitパターン」として知られる量子コンピューティングのフレームワークを使用します。これはワークフローを以下のステップに分解するものです:
- ステップ1:古典的な入力を量子問題にマッピングする
- ステップ2:量子実行のために問題を最適化する
- ステップ3:Qiskit RuntimeプリミティブでExecuteする
- ステップ4:後処理と古典的な解析
基本的にこれらのステップに従いますが、常に明示的にラベル付けするとは限りません。
まず、Runtimeプリミティブを含む必要なパッケージをいくつか読み込みましょう。また、利用可能な中で最も混雑していない量子コンピューターを選択します。
以下には、初回使用時に認証情報を保存するためのコードがあります。ノートブックを共有する際に認証情報が誤って共有されないよう、環境に保存した後はノートブックからこの情報を削除してください。詳細については、IBM Cloudアカウントのセットアップおよび信頼されていない環境でのサービスの初期化を参照してください。
from numpy import pi
# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService
# Syntax for first saving your token. Delete these lines after saving your credentials.
# QiskitRuntimeService.save_account(channel='ibm_quantum_platform',
# instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR-API_KEY>', overwrite=True, set_as_default=True)
# service = QiskitRuntimeService(channel='ibm_quantum_platform')
# Load saved credentials
service = QiskitRuntimeService()
# Load the Runtime primitive and session
from qiskit_ibm_runtime import (
Batch,
SamplerV2 as Sampler,
EstimatorV2 as Estimator,
)
# Use the least busy backend
backend = service.least_busy(min_num_qubits=127)
print(backend.name)
ibm_sherbrooke
レッスン中に学生が利用可能な量子コンピューティング時間を使い切った場合は、以下の行のコメントを解除して、上で選択した量子コンピューターのノイズ挙動を部分的に模倣するシミュレーターをセットアップするために使用できます。
# Import an estimator, this time from qiskit (we will import from Runtime for real hardware)
from qiskit_aer.primitives import SamplerV2, EstimatorV2
from qiskit_aer.noise import NoiseModel
# Generate the noise model from the backend properties
noise_model = NoiseModel.from_backend(backend)
noisy_sampler = SamplerV2(options={"backend_options": {"noise_model": noise_model}})
noisy_estimator = EstimatorV2(options={"backend_options": {"noise_model": noise_model}})
演算子Zの固有状態は、別の演算子Xの固有状態ではないことを思い出してください。では今、 軸および 軸に沿った測定を行うことで、実験的にそれを観察しましょう。 に沿った測定には単に qc.measure() を使います。IBMの量子コンピューターは に沿って測定するように設計されているからです。しかし に沿って測定するには、実質的に 軸を測定する向きに移動させるようにシステムを回転させる必要があります。これはアダマールGateで実現されます。 に沿った測定にも同様のステップが必要です。必要なステップを便宜上ここにまとめます:
- に沿って測定する場合:
qc.measure() - に沿って測定する場合:
qc.h()の後にqc.measure() - に沿って測定する場合:
qc.sdg()、qc.h()、qc.sの後にqc.measure()
ステップ1:古典的な入力を量子問題にマッピングする
この場合、マッピングのステップは上述の測定と回転を量子Circuit(回路)で表現するだけです:
# Step 1: Map
# Import some general packages
from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(2, "c")
qc = QuantumCircuit(qr, cr)
# Add a first measurement
qc.measure(qr, cr[0])
qc.barrier()
# Change basis so that measurements made on quantum computer which normally tell us about z,
# now tell us about x.
qc.h(qr)
# Add a second measurement
qc.measure(qr, cr[1])
qc.draw("mpl")
ステップ2:量子実行のために問題を最適化する
このステップでは、実行したい操作を特定の量子コンピューターの機能の観点から表現し、問題を量子コンピューターのレイアウトにマッピングします。
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
ステップ3:Qiskit RuntimeプリミティブでExecuteする
Samplerを使用して測定の統計を収集できます。Samplerプリミティブを mode = backend とすることで実際の量子コンピューター上で実行するように構成します。他のワークフローには別のモードがあり、以下でその一つを使用します。Samplerは「pub」(Primitive Unified Bloc)のリストと共にrun()メソッドを呼び出すことで使用されます。各pubには最大3つの値が含まれており、それらが合わさって推定器が完了すべき計算の単位を定義します:Circuit、オブザーバブル、パラメーター。Circuit、オブザーバブル、パラメーターのリストをそれぞれ提供することもできます。詳細については、PUBの概要を参照してください。
実際の量子物理実験を行うために、実際の量子コンピューターで実行します。実際の量子コンピューターでの割り当て時間を使い切った場合は、以下の量子コンピューター用のコードをコメントアウトし、シミュレーターで実行するためのコードのコメントを解除してください。
# Step 3: Run the job on a real quantum computer
sampler = Sampler(mode=backend)
pubs = [qc_isa]
job = sampler.run(pubs)
res = job.result()
counts = res[0].data.c.get_counts()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_sampler.run([qc_isa])
# res=job.result()
# counts=res[0].data.c.get_counts()
ステップ4:後処理
これは後処理の特に単純なケースで、カウントを視覚化するだけです。
Qiskitは最も番号が小さいアイテムを最後(右)に表示するという規則でQubit、測定値などを順序付けることに注意してください。この規則は「リトルエンディアン」と呼ばれます。これは、以下の「10」というラベルの付いた列が、最初の測定値が「0」、2回目の測定値が「1」であったカウントを指すことを意味します。
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)
この規則が気に入らない場合は、marginal_counts を使用して各測定の結果を別々に視覚化できます:
from qiskit.result import marginal_counts
plot_histogram(
marginal_counts(counts, indices=[0]), title="Counts after first measurement"
)
plot_histogram(
marginal_counts(counts, indices=[1]), title="Counts after second measurement"
)
デフォルトでは、Qiskitの状態は 状態に初期化されます。したがって、最初の測定のほぼ全てが を返したのは驚くことではありません。しかし、2回目の測定(状態の への射影についての情報を与えるもの)では、ほぼ均等に分かれていたことに注目してください。 に沿った測定結果が非常に予測可能なこの状態が、 に沿った測定結果は非常に予測不可能な結果を与えるようです。これを詳しく調べましょう。
測定の順序を逆にするとどうなるでしょうか?最初にアダマールGateを使用して、 で が測定される確率の統計を取ることができます。次に2回目の測定では、2つ目のアダマールGateを使用して 基底に戻ります。
# Step 1:
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(2, "c")
qc = QuantumCircuit(qr, cr)
# Change basis to measure along x.
qc.h(qr)
qc.measure(qr, cr[0])
qc.barrier()
# Change our basis back to z and make a second measurement
qc.h(qr)
qc.measure(qr, cr[1])
qc.draw("mpl")
# Step 2: Transpile the circuit for running on a quantum computer
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
# Step 3: Run the job on a real quantum computer
sampler = Sampler(mode=backend)
pubs = [qc_isa]
job = sampler.run(pubs)
res = job.result()
counts = res[0].data.c.get_counts()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_sampler.run([qc_isa])
# res=job.result()
# counts=res[0].data.c.get_counts()
# Step 4: Post-process
from qiskit.visualization import plot_histogram
plot_histogram(counts)
ここでは、さらに予測不可能な結果が得られているようです!以前は少なくとも最初の測定の結果は分かっていましたが、今では全ての可能な状態にわたってかなり均等な分布になっています。なぜこうなったのかは、それほど難しくありません。 から始まりましたが、それは に従い、 と の50対50の混合です。 したがって、最初の測定でグラフの0と1にマッピングされる+または-の状態が得られる確率が等しいはずであることは明らかです。 に沿った測定は、状態を固有状態 または固有状態 のどちらかに崩壊させます。これらの状態のそれぞれは、 に従い、 と の50対50の混合です。 したがって、システムが の固有状態にある場合、 に沿った測定は と の両方を返し、ほぼ等しい確率でそうなります。 最初の例では、ある状態は特定の測定の結果が非常に予測可能で、他の測定の結果は予測不可能であることを示しました。今の例では、それよりも悪い状況になり得ることを示しています。測定の順序を入れ替えるだけで、両方の測定の結果が予測不可能な状態が存在します。ある状態について、ある量がどれほど確定的または不確定であるかを調べましょう。
不確定性の計算
これは不確定性(分散)を使用して定量化できます。「不確定性」は分布の「分散」の平方根として定義されることが多いです。つまり、ある観測量 の不確定性は と表記され、次のように与えられます:
パウリ行列の場合、 であるため、これは次のようになります:
具体的な例に適用してみましょう。状態 から始めて、その状態での観測量 の不確定性を求めましょう。
理解度チェック
状態 における の不確かさを手計算で求めてください。
Answer
与えられた状態では、次のようになります:
任意の初期状態は qc.initialize() を使って作成できます。ここで虚数単位の構文は であることに注意してください。
# Step 1: Map the problem into a quantum circuit
from qiskit.quantum_info import SparsePauliOp
import numpy as np
obs = SparsePauliOp("X")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state
qc.initialize([1, 1j] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
estimator = Estimator(mode=backend)
pubs = [(qc_isa, obs_isa)]
job = estimator.run([[qc_isa, obs_isa]])
res = job.result()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc_isa,obs_isa]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print(res[0].data.evs)
-0.02408454165642664
上記の式によれば、 同じ状態を保ちつつ、今度は の期待値を求めてみましょう:
# Step 1: Map the problem into a quantum circuit
obs = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state to |+>_y
qc.initialize([1, 1j] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs_isa = obs.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
estimator = Estimator(mode=backend)
pubs = [(qc_isa, obs_isa)]
job = estimator.run(pubs)
res = job.result()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc_isa,obs_isa]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print(res[0].data.evs)
0.04958271968581247
先ほどと同じ計算を行えば、分散が再び 1.0 に非常に近いことがわかります。つまり と結論づけられます。ところで、これ以上よくなる(あるいは悪くなる)余地はあるのでしょうか?
位置 とそれに対応する方向の運動量 の間には不確定性関係があることを思い出してください。それらの変数に対する最もよく知られた形式はおそらく、 これしか知らなければ、 と にも同様の基本的な不確かさの下限があると思いたくなるかもしれません。もしかすると、積 がゼロに近づくことは不可能なのでしょうか?別の状態を試して確かめてみましょう。今度は を使います。何が起こるか見てみましょう。以下のコードでは、estimator が同じジョブ送信で 2 セットの回路とオブザーバブルを受け取れることに注意してください。
# Step 1: Map the problem into a quantum circuit
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Initialize the state
qc.initialize([1, 1] / np.sqrt(2))
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, obs1_isa), (qc_isa, obs2_isa)]
job = estimator.run(pubs)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([[qc,obs1],[qc,obs2]])
# res=job.result()
# Step 4: Return the result in classical form, and analyze.
print("The expectation value of the first observable is: ", res[0].data.evs)
print("The expectation value of the second observable is: ", res[1].data.evs)
The expectation value of the first observable is: 1.0011036174126302
The expectation value of the second observable is: 0.0029429797670141016
の期待値は 1.0 に近いはずですが、1.0 を超えることはありません。ごくわずかに 1.0 を超えても心配しないでください。これはノイズや読み出しエラーなどの要因によるものです。これは非常に重要なトピックですが、今は無視してもかまいません。
の期待値が 1.0 に非常に近い( の分散が非常に小さい)結果が得られました。これにより、2 つの分散の積はかなり小さくなります:
これは厳密にゼロではありませんが、Pauli 演算子の固有値()と比べると小さくなっています。ところで、線形位置と運動量の間の不確定性関係は、演算子 と の交換子を明示的に使って別の形で書くことができたことを思い出すかもしれません:
ここで
は と の交換子です。
この形式は Pauli 演算子に最も簡単に拡張できます。一般に、2 つの演算子 と に対して、
Pauli 行列 と の場合、次を計算するために が必要です:
ここでこれを示し、同様の計算は演習として読者にお任せします:
これは十分な答えですが、もう一歩進めると、
したがって不確定性関係は次のようになります:
理解度チェック
と を求めてください。それを使って と 、 と の間の不確定性関係を書き下してください。
Answer
一般的な不確定性関係と組み合わせると、
整合性を確認する
次に進む前に、これが以前の結果と整合しているか確認しましょう。状態 を使い、 が得られました。この積は次以上でなければなりません:
確かに が成立しています。 以下の問いを通じて、これらの結果への直感を養ってください:
理解度チェック
以下の項目にまとめて答えてください:
(a) の不確かさがゼロになると期待される状態はどれですか?
(b) の不確かさがゼロになると期待される状態はどれですか?
(c) 期待値 がゼロになる状態はどれですか?
(d) 上記の答えは の場合と整合していますか?
(e) estimator を使ってこれを明示的に確認するコードを書いてください。
Answer
(a) 演算子の固有状態では の不確かさがゼロになると期待されます。実際、 を使うと、
(b) 演算子の固有状態では の不確かさがゼロになると期待されます。実際、 を使うと、
(c) 軸上で正の射影と負の射影が同じ頻度で得られる状態、つまり と の固有状態では が期待されます。
(d) はい。 または の固有状態では不確かさの積 が非常に小さくなる()と期待されます。同じ状態では も期待されるため、不確定性関係は満たされます。
(e) 以下のようなコードで確認できます:
obs1 = SparsePauliOp.from_list(
[("X", 1.000)]
)
obs2 = SparsePauliOp.from_list(
[("Y", 1.000)]
)
obs3 = SparsePauliOp.from_list(
[("Z", 1.000)]
)
qc = QuantumCircuit(1,1)
qc.ry(pi/2,0)
job = estimator.run([(qc, [[obs1], [obs2], [obs3]])], precision=0.001)
res=job.result()
結果はすべての期待値を返します。すべての期待値を取得し、不確かさを計算するには次のようにします:
xs=res[0].data.evs[0]
ys=abs(res[0].data.evs[1])
zs=res[0].data.evs[2]
import math
prodxz=((1-xs[i]*xs[i])**0.5)*(1-zs[i]*zs[i])**0.5
以下の項目にまとめて答えてください:
(a) が大きな値になると期待される状態を考えてみてください。
(b) その状態では の不確かさは大きいですか、小さいですか?
(c) その状態では の不確かさは大きいですか、小さいですか?
(d) 上記の答えは の場合と整合していますか?
(e) estimator を使ってこれを明示的に確認するコードを書いてください。
Answer
(a) の固有状態 では が期待されます。
(b) 状態 では、 を測定すると正と負の結果が等しい頻度・確率で得られるため、 の不確かさは大きいと期待されます。
(c) 状態 では、 を測定すると正と負の結果が等しい頻度・確率で得られるため、 の不確かさは大きいと期待されます。
(d) はい。 の固有状態、特に では不確かさの積 が大きくなると期待されます。同じ状態では も期待されます。したがって、この状態では と の両方がかなり大きく、不確定性関係が満たされるのはもっともなことです。
(e) 以下のようなコードで確認できます:
obs1 = SparsePauliOp.from_list(
[("X", 1.000)]
)
obs2 = SparsePauliOp.from_list(
[("Y", 1.000)]
)
obs3 = SparsePauliOp.from_list(
[("Z", 1.000)]
)
qc = QuantumCircuit(1,1)
qc.rx(-pi/2,0)
job = estimator.run([(qc, [[obs1], [obs2], [obs3]])], precision=0.001)
res=job.result()
結果はすべての期待値を返します。すべての期待値を取得し、不確かさを計算するには次のようにします:
xs=res[0].data.evs[0]
ys=abs(res[0].data.evs[1])
zs=res[0].data.evs[2]
import math
prodxz=((1-xs[i]*xs[i])**0.5)*(1-zs[i]*zs[i])**0.5
不確定性関係の検証
上記のテストは、状態ベクトル という 1 つの選択に対してのみ不確定性関係の妥当性を示しました。これが一般的に実験と整合することを確認するには、多くの状態ベクトルの選択に対して estimator を使って同様の計算を行う必要があります。まず、パラメーター を使って異なる初期状態を生成するために RY Gate を使い、状態ベクトルを 軸から回転させてみましょう。
# The calculation below uses approximately 3-4 minutes of QPU time.
# Step 1: Map the problem into a quantum circuit
from qiskit.circuit import Parameter
import numpy as np
# Specify observables
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Y")
obs3 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Rotate away from |0>
theta = Parameter("θ")
qc.ry(theta, 0)
params = np.linspace(0, 2, num=21)
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
obs3_isa = obs3.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, [[obs1_isa], [obs2_isa], [obs3_isa]], [params])]
job = estimator.run(pubs, precision=0.01)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([(qc, [[obs1], [obs2], [obs3]], [params])])
# res=job.result()
# Step 4: Post-processing and classical analysis.
xs = res[0].data.evs[0]
ys = abs(res[0].data.evs[1])
zs = res[0].data.evs[2]
# Calculate uncertainties
delx = []
delz = []
prodxz = []
for i in range(len(xs)):
delx.append(abs((1 - xs[i] * xs[i])) ** 0.5)
delz.append(abs((1 - zs[i] * zs[i])) ** 0.5)
prodxz.append(delx[i] * delz[i])
# Here we can plot the results from this simulation.
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r"$\Delta$ X")
plt.plot(params, ys, label=r"$\langle$ Y $\rangle$")
plt.plot(params, delz, label=r"$\Delta$ Z")
plt.plot(params, prodxz, label=r"$\Delta$X $\Delta$Z")
plt.xlabel(r"$\theta$")
plt.ylabel("Expectation/Uncertainty Values")
plt.legend()
plt.show()
赤い曲線 は常にオレンジの曲線 より大きいことに注目してください。不確かさの積が下限に近づいて小さくなることもあれば、下限から遠ざかって大きくなることもありますが、常に不確定性関係を満たしています。
もちろん、下限 が常にゼロに非常に近いため、これは不確定性関係の最良のテストとは言えないかもしれません。 の固有状態により大きな射影を持つ量子状態を使ってみましょう。具体的には、引き続き を 軸からさまざまな角度で回転させますが、その状態をさらに 軸周りにある角度(たとえば )だけ回転させて、どうなるかを見てみます。
# The calculation below uses approximately 3-4 minutes of QPU time.
from qiskit.circuit import Parameter
import numpy as np
# Step 1: Map the problem to a quantum circuit
# Specify observables
obs1 = SparsePauliOp("X")
obs2 = SparsePauliOp("Y")
obs3 = SparsePauliOp("Z")
# Define registers
qr = QuantumRegister(1, "q")
cr = ClassicalRegister(1, "c")
qc = QuantumCircuit(qr, cr)
# Rotate away from |0> along one plane, and then along a transverse direction.
theta = Parameter("θ")
qc.ry(theta, 0)
qc.rz(pi / 4, 0)
params = np.linspace(0, 2, num=21)
# Step 2: Transpile the circuit
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
obs1_isa = obs1.apply_layout(layout=qc_isa.layout)
obs2_isa = obs2.apply_layout(layout=qc_isa.layout)
obs3_isa = obs3.apply_layout(layout=qc_isa.layout)
# Step 3: Run the circuit on a real quantum computer
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
pubs = [(qc_isa, [[obs1_isa], [obs2_isa], [obs3_isa]], [params])]
job = estimator.run(pubs, precision=0.01)
res = job.result()
batch.close()
# Run the job on the Aer simulator with noise model from real backend
# job = noisy_estimator.run([(qc, [[obs1], [obs2], [obs3]], [params])])
# res=job.result()
# Step 4: Post-processing and classical analysis.
xs = res[0].data.evs[0]
ys = abs(res[0].data.evs[1])
zs = res[0].data.evs[2]
# Calculate uncertainties
delx = []
delz = []
prodxz = []
for i in range(len(xs)):
delx.append(abs((1 - xs[i] * xs[i])) ** 0.5)
delz.append(abs((1 - zs[i] * zs[i])) ** 0.5)
prodxz.append(delx[i] * delz[i])
# Here we can plot the results from this simulation.
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r"$\Delta$ X")
plt.plot(params, ys, label=r"$\langle$ Y $\rangle$")
plt.plot(params, delz, label=r"$\Delta$ Z")
plt.plot(params, prodxz, label=r"$\Delta$X $\Delta$Z")
plt.xlabel(r"$\theta$")
plt.ylabel("Expectation/Uncertainty Values")
plt.legend()
plt.show()
今度は不確かさ の下限が本当に試されていることがわかります!赤い曲線はオレンジの曲線にずっと近づいています。実際、ノイズがなければ、不確定性関係はある 1 点で厳密に等号が成立()するはずです。ノイズや読み出しエラーがある場合、実行によっては が をごくわずかに上回ることがあっても不思議ではありません。これは不確定性の真の破れではなく、ゼロでないエラーによるアーティファクトに過ぎません。
理解度チェック
をできる限り大きくするには、どのようにすればよいか説明してください。
Answer
現在のコードには、デフォルトの初期状態 を 軸からパラメーター化された角度 だけ回転させ、さらに 軸周りに の角度だけ回転させる行があります。これにより、状態ベクトルが 軸の方向へ一部回転します。
qc.ry(theta,0)
qc.rz(pi/4,0)
軸周りの回転を から に変更することで、 の固有状態まで完全に回転させることができます。
qc.ry(theta,0)
qc.rz(pi/2,0)
他の変更は必要ありません。
コードを変更するか、コピーして、 の期待値を最大化した状態で不確定性関係の検証を実装してください。不確定性関係は成立しますか?
Answer
上記の例のコードをそのまま使用し、以下を
qc.rz(pi/4,0).
次のように置き換えます。
qc.rz(pi/2,0)
得られる図は以下のようになるはずです。不確定性原理は引き続き成立します。

上記のコードを修正して同様の図を作成し、量子コンピューターの測定結果から積 が期待通りに振る舞うことを示してください。任意の状態のセットを選んで構いません。
Answer
上記の例のコードをそのまま使用できます。実際、上記の結果をそのまま利用し、期待値を使って異なる不確定性を計算するだけで済みます。たとえば、以下のコードを使うことができます。
xs=res[0].data.evs[0]
ys=res[0].data.evs[1]
zs=abs(res[0].data.evs[2])
import math
delx = []
dely = []
prodxy=[]
for i in range(len(xs)):
delx.append((1-xs[i]*xs[i])**0.5)
dely.append((1-ys[i]*ys[i])**0.5)
prodxy.append(((1-xs[i]*xs[i])**0.5)*(1-ys[i]*ys[i])**0.5)
また、次のようにプロットできます。
import matplotlib.pyplot as plt
plt.plot(params, delx, label=r'$\Delta$ X')
plt.plot(params, dely, label=r'$\langle$ Y $\rangle$')
plt.plot(params, zs, label=r'$\Delta$ Z')
plt.plot(params, prodxy, label=r'$\Delta$X $\Delta$Z')
plt.xlabel(r'$\theta$')
plt.ylabel('Expectation/Uncertainty Values')
plt.legend()
plt.show()
チャレンジ: の多くの値をスキャンしたように、 の多くの値をスキャンするコードを書き、不確定性関係が決して破られないことを示す3次元プロットを作成してください。任意の観測量を選んで構いません。
問題
インストラクターは、この簡単なアンケートに記入することで、これらのノートブックの使用方法に関する解答集およびカリキュラムへの配置ガイダンス付きバージョンをリクエストできます。
重要な概念
- 位置と線形運動量、スピンの成分など、多くの物理的観測量のペアの間に不確定性関係が存在します。
- パウリ行列は可換ではありません。これは、スピンのすべての成分を同時に知る・決定することができないという事実の数学的な反映です。
- 量子コンピューティングはパウリ演算子・行列を多用するため、パウリ演算子の不確定性関係、および密接に関連したスピン演算子についても知っておくことが有用です。
- 二つの演算子 と の不確定性に関する一般公式は です。
- ある演算子 の固有状態 は、その演算子に関連する物理的観測量の不確定性をゼロにします。実験的にも となります。
- ある演算子 の固有状態 は、 と可換でない演算子 に対してより大きな不確定性をもたらします。
- 実際の量子コンピューターを使った実験結果は、物理演算子の行列表現から得られる直観を裏付けます。
正誤問題(T/F)
- T/F と は同時測定できるが、 は同時測定できない。
- T/F と は同時測定できるが、 は同時測定できない。
- T/F 線形位置演算子と線形運動量演算子は可換ではない。
- T/F IBM の量子コンピューターはデフォルトで 方向に測定するため、他の方向に沿って測定するには回転を行う必要がある。
- T/F 以下のCircuitは、 を測定してから を測定することと等価である。
多肢選択問題(MC)
-
以下の図が示しているのは、次のどの不確定性関係ですか?
- a.
- b.
- c.
- d. 上記のいずれでもない

-
方向に沿って測定を行う標準的な手順はどれですか?
- a.
qc.measure()のみ - b.
qc.h()の後にqc.measure() - c.
qc.h()、qc.h()の後にqc.measure() - d.
qc.h()、qc.s、qc.h()の後にqc.measure() - e.
qc.sdg()、qc.h()、qc.sの後にqc.measure() - f.
qc.sdg()、qc.h()、qc.s、qc.h()の後にqc.measure()
- a.
-
次のうち、最大の期待値 をもたらす状態はどれですか?
- a.
- b.
- c. ( とも呼ばれる)
- d. ( とも呼ばれる)
- e. ( とも呼ばれる)
- f. ( とも呼ばれる)
-
次のうち、最大の不確定性 をもたらす状態はどれですか?
- a.
- b. ( とも呼ばれる)
- c. ( とも呼ばれる)
- d. a と b が同率
- e. b と c が同率
- f. a、b、c がすべて同率
ディスカッション問題
-
この不確定性という概念は、スピンをデカルト空間のベクトル矢印として捉えるという考え方と何か矛盾しますか?ブロッホ球上ではどうでしょうか?
-
軸と 軸の中間の方向に測定装置を向けたとします。何が起こりますか?その方向に沿って測定することは可能ですか?これは と の不確定性とどのように関係しますか?
-
ここで得られた結果を自分自身で確かめるために、どのような追加実験を行いたいですか?