2024年11月11日月曜日

How to run quantum circuits on the development platform Qiskit

[Abstract] IBM Qiskit is used as a typical development environment for quantum computing. Its version is frequently updated, and some parts are soon deprecated, which can be confusing. The description of quantum gates and quantum circuits remains almost the same, but there are frequent changes in simulations and execution methods on actual machines. Here, I would like to note three typical execution methods at the present time (2024-11-10).

🔴Example: Quantum computation part of Shor's prime factorization algorithm

Here, we will focus only on running the order finding quantum circuit, which is the main part of Shor's algorithm. Fig.1 shows the prime factorization of the very small integer 15 (15 = 3 × 5) for demonstration purposes. We will not explain the relationship between the entire Shor algorithm and the quantum circuit in Fig.1 this time, so if necessary, please refer to the following past articles.

🔴[1] Simulation with Qiskit Sampler (run on local PC)

Qiskit Sampler is the most common simulator for running a quantum circuit (name: qc) like the one in Fig.1 (including measuring the lower three qubits). The main points of its use are as follows. The results of this simulation (measurement results of 1,000 shots) are shown in Fig.2.

# Running the Simulation
from qiskit_aer.primitives import Sampler
sampler = Sampler()
result = sampler.run(qc, shots=1000).result()

# Extraction and visualization of measurement results
quasi_dists = result.quasi_dists
binary_quasi_dist = quasi_dists[0].binary_probabilities()
counts_dict = quasi_dists[0].binary_probabilities()
counts = Counts(counts_dict)
plot_histogram(counts)


🔴[2] Simulation incorporating a noise model of the actual machine (run on a local PC)

In the above, the simulation results (Fig.2) show that the counts corresponding to the four bases are approximately 25% each, and the counts of the other bases are zero as expected because there is no noise. In addition to using a normal sampler like this, it is also possible to perform simulations that reflect the noise generated by the actual quantum computer.

Fig. 3 shows the result of incorporating a noise model generated by a real machine (127-qubits) named ibm_sherbrooke into AerSimulator and running it. Indeed, the effects of noise that did not occur in Fig. 2 are apparent. This may be useful for preliminary examination before running on a real machine.

# important imports
from qiskit_aer import AerSimulator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler

# Set the noise model of the real machine
real_backend = service.backend("ibm_sherbrooke")
aer = AerSimulator.from_backend(real_backend)
pm = generate_preset_pass_manager(backend=aer, optimization_level=1)
isa_qc = pm.run(qc) # transpile for the real machine
sampler = Sampler(mode=aer)
result = sampler.run([isa_qc],shots=1000).result() # execution

# Extraction and visualization of measurement results
pub_result = result[0]
counts = pub_result.data.c.get_counts() # Note the 'c' !
plot_histogram(counts)

🔴[3] Execution on an actual IBM Quantum machine (submitting a job via the web)

Next, the job was submitted to an actual IBM Quantum machine via the web and executed. The machine was ibm_sherbrooke, the same as that given in the noise model above. The job was executed in batch mode, so the execution results were retrieved via the web after it was completed. This is shown in Fig. 4, and it was found to be almost identical to the simulation results shown in Fig. 3, which reflect the above noise model.

# Automatically select machines with low load
from qiskit_ibm_runtime import SamplerV2 as Sampler
service = QiskitRuntimeService(channel="ibm_quantum", token= "***")
be = service.least_busy(simulator=False, operational=True)
print(f"QPU backend:{be}")

# Transpile for real machine and submit the job
pm = generate_preset_pass_manager(optimization_level=1, backend=be)
ic = pm.run(qc) # Transpiled circuit
job = Sampler(be).run([ic], shots= 1000)
print(f"job ID: {job.job_id()}")
print(f"job statusI: {job.status()}")

# After execution, the results are retrieved and displayed
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService(
    channel='ibm_quantum',
    instance='ibm-q/open/main',
    token='token for the job'
)
job = service.job('jab ID')
job_result = job.result()
counts = job.result()[0].data.c.get_counts()
plot_histogram(counts)

The execution status is shown in Fig. 5. Usage = 2 sec. Free users are limited to 10 minutes of usage per month. This is sufficient for testing simple quantum circuits, but caution is required when testing slightly more complex quantum circuits, as this can result in unexpectedly high usage. At present, there are three models of actual machines available for free use, as shown in Fig. 6. For paid users, eight more models of actual machines can be used in addition to these.


🔴 Differences between the results of a real machine and a simulator

Currently, quantum computers generate various noises, which causes errors. For example, the difference between the results of a pure simulator (Fig. 2) and the results of a real machine (Fig. 4) shows this. Although it cannot be said in general, errors that occur on a real machine can have a large impact on the necessary calculations. However, in the case of this example problem, due to the nature of probabilistically searching for an order, it can be said that the difference between Fig. 2 and Fig. 4 is almost no problem.

量子コンピューティング開発環境Qiskitでの実行方法

English version here
【要旨】
量子コンピューティングの代表的な開発環境として、IBM Qiskitを利用している。そのバージョンアップは頻繁になされて、すぐにdeprecated(非推奨、または廃止)となる部分が多く、困惑する場合がある。量子ゲートや量子回路の記述などはほとんど変わらないが、シミュレータ、および実機での実行方法などの変更が多発する。ここでは、現時点(2024-11-10)での典型的な実行方法3つをメモして置きたい。

🔴例題:Shorの素因数分解アルゴリズムの量子計算部分
 ここでは、Shorのアルゴリズムの主要部である位数計算(order finding)量子回路を動かすことだけに注目する。Fig.1は、デモとして動かすための、極く小さな整数15の素因数分解(15 = 3 × 5)の場合である。Shorのアルゴリズム全体とFIg.1の量子回路との関係などは今回は説明しないので、例えば以下のような過去記事をご覧いただきたい。

🔴[1]Qiskit Samplerによるシミュレーション(ローカルPCで実行)
 Fig.1のような量子回路(名称:qc)の実行(下位3量子ビットの測定を含む)を行うための最も一般的なシミュレータとして、Qiskit Samplerがある。その利用の要点は以下のとおりである。このシミュレーションの結果(1,000 shotsの測定結果)をFig.2に示す。

# シミュレーションの実行
from qiskit_aer.primitives import Sampler
sampler = Sampler()
result = sampler.run(qc, shots=1000).result()

# 測定結果の取り出しと図示
quasi_dists = result.quasi_dists
binary_quasi_dist = quasi_dists[0].binary_probabilities()
counts_dict = quasi_dists[0].binary_probabilities()
counts = Counts(counts_dict)
plot_histogram(counts)


🔴[2]実機のノイズモデルを組み込んだシミュレーション(ローカルPCで実行)
 上記では、シミュレーション結果(Fig.2)として、4つの基底に対応するカウントがほぼ25%づつで、それ以外の基底のカウントは、ノイズがないので、理論通りゼロとなった。このような通常のSamplerによる以外に、量子コンピュータ実機で発生するノイズを反映させたシミュレーションを行うこともできる。
 Fig.3は、ibm_sherbrookeという名の実機(127-qubits)で発生するノイズモデルを、AerSimulatorに組み込んで実行した結果である。確かに、Fig.2では発生しなかったノイズによる影響が出ている。実機で実行する前の事前検討などに有用であろう。

# 重要なimport
from qiskit_aer import AerSimulator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler

# リアルマシンのノイズモデルをセット
real_backend = service.backend("ibm_sherbrooke")
aer = AerSimulator.from_backend(real_backend)
pm = generate_preset_pass_manager(backend=aer, optimization_level=1)
isa_qc = pm.run(qc) # 実マシン向けのtranspile
sampler = Sampler(mode=aer)
result = sampler.run([isa_qc],shots=1000).result() # 実行

# 測定結果の取り出しと図示
pub_result = result[0]
counts = pub_result.data.c.get_counts() # 'c'を指定することに注意!
plot_histogram(counts)

🔴[3]IBM Quantumマシン実機での実行(web経由でジョブを投入)
 次に、IBM Quantumマシン実機へweb経由でジョブを投入し、実行を行った。マシンは、上記のノイズモデルで与えたものと同じibm_sherbrookeである。ジョブはバッチ形式で実行されるので、その終了後にWeb経由で実行結果を取り出す。それを表示したものがFig.4である。上記のノイズモデルを反映したシミュレーション結果Fig.3とほぼ同一であることが確認できた。

# 負荷の少なそうなマシンを自動選択
from qiskit_ibm_runtime import SamplerV2 as Sampler
service = QiskitRuntimeService(channel="ibm_quantum", token= "***")
be = service.least_busy(simulator=False, operational=True)
print(f"QPUバックエンド:{be}")

# 実マシン向けのtranspileを行い、Jobを投入
pm = generate_preset_pass_manager(optimization_level=1, backend=be)
ic = pm.run(qc) # Transpile結果
job = Sampler(be).run([ic], shots= 1000)
print(f"ジョブID: {job.job_id()}")
print(f"ジョブI状態: {job.status()}")

# 実行終了後に、結果を取り出し、表示。
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService(
    channel='ibm_quantum',
    instance='ibm-q/open/main',
    token='jobに対応するトークン'
)
job = service.job('jab ID')
job_result = job.result()
counts = job.result()[0].data.c.get_counts()
plot_histogram(counts)

 この実行の状況をFig.5に示した。Usage = 2 secとなっている。無償ユーザは、毎月10分までのUsageという制約がある。簡単な量子回路の試験には十分であるが、少し複雑な量子回路になると想定外に多くのUsageを使うことになるので、注意が必要である。なお、現時点では、無償で使える実機はFig.6に示すとおり、3機種であった。有償の場合は、これらの他にさらに8機種の実機が利用できる。


🔴実マシンとシミュレータの結果の相違について
 現状では、量子コンピュータは種々のノイズが発生するので誤りが起こる。例えば、純粋のシミュレータの結果Fig.2と、実マシンによる結果Fig.4の相違がそれを示している。一概には言えないが、実機で起こる誤りが、必要な計算に与える影響は大きい場合がある。だが、本例題に限って言えば、確率的に位数(order)を探すという性質上、Fig.2とFig.4の差はほとんど問題にならないと言える。