azure-quantum
Python パッケージを使用して Qiskit 量子回路を送信する方法について説明します。 組み込みの azure-quantum
Python パッケージがある Azure Quantum ノートブックを使用するか、ローカル コンピューターから、Qiskit 回線を Azure Quantum に送信できます。 ローカル スパース シミュレーターを使用して回線をテストすることもできます。
詳細については、量子回路に関するページを参照してください。
前提条件
インストールについての詳細は、 QDK 拡張機能を設定するを参照してください。
Azure サブスクリプションの Azure Quantum ワークスペース。 ワークスペースを作成するには、Azure Quantum ワークスペースの作成に関するページを参照してください。
Python と Pip がインストールされた Python 環境。
Azure Quantum Development Kit、Python、および Jupyter 拡張機能がインストールされている VS Code。
[qiskit] タグが付いた Azure Quantum
azure-quantum
Python パッケージ。python -m pip install --upgrade azure-quantum[qiskit] qsharp ipykernel
重要
Qiskit の最新バージョンがあることを確認します。 詳細については、「 azure-quantum Python パッケージの更新を参照してください。
Note
Jupyter Python カーネル
ipykernel
が検出されない場合、VS Code によってインストールするように求められます。
新しい Jupyter Notebook を作成する
- VS Code で、[表示] > [コマンド パレット] を選択して、[作成: 新しい Jupyter Notebook] を選択します。
- 右上の VS Code は、ノートブック用に選択された Python のバージョンと仮想 Python 環境を検出して表示します。 複数の Python 環境がある場合は、右上のカーネル ピッカーを使用してカーネルを選択する必要があります。 環境が検出されなかった場合は、VS Code の Jupyter Notebooks のセットアップ情報を参照してください。
必要なインポートを読み込む
ノートブックの最初のセルで、次のコードを実行して、必要なインポートを読み込みます。
import azure.quantum
from azure.quantum import Workspace
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
from azure.quantum.qiskit import AzureQuantumProvider
Azure Quantum サービスに接続する
Azure Quantum サービスに接続するには、リソース ID と Azure Quantum ワークスペースの場所が必要です。
Azure アカウントにログインし、 https://portal.azure.com、
Azure Quantum ワークスペースを選択し、 Overview に移動します。
フィールド内のパラメーターをコピーします。
ノートブックに新しいセルを追加し、アカウント情報を使用して、Azure Quantum ワークスペースに接続する Workspace
オブジェクトと AzureQuantumProvider
オブジェクトを作成します。
workspace = Workspace(
resource_id = "", # Add the resourceID of your workspace
location = "" # Add the location of your workspace (for example "westus")
)
provider = AzureQuantumProvider(workspace)
すべてのバックエンドを一覧表示する
これで、ワークスペースで使用できるすべての量子コンピューティング バックエンドを出力できます。
print("This workspace's targets:")
for backend in provider.backends():
print("- " + backend.name())
This workspace's targets:
- ionq.qpu
- ionq.qpu.aria-1
- ionq.simulator
- microsoft.estimator
- quantinuum.hqs-lt-s1
- quantinuum.hqs-lt-s1-apival
- quantinuum.hqs-lt-s2
- quantinuum.hqs-lt-s2-apival
- quantinuum.hqs-lt-s1-sim
- quantinuum.hqs-lt-s2-sim
- quantinuum.qpu.h1-1
- quantinuum.sim.h1-1sc
- quantinuum.sim.h1-1e
- rigetti.sim.qvm
- rigetti.qpu.ankaa-3
単純な回路を実行する
最初に、簡単な Qiskit 回路を作成して実行します。
# Create a Quantum Circuit acting on the q register
circuit = QuantumCircuit(3, 3)
circuit.name = "Qiskit Sample - 3-qubit GHZ circuit"
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure([0,1,2], [0, 1, 2])
# Print out the circuit
circuit.draw()
┌───┐ ┌─┐
q_0: ┤ H ├──■───────┤M├──────
└───┘┌─┴─┐ └╥┘┌─┐
q_1: ─────┤ X ├──■───╫─┤M├───
└───┘┌─┴─┐ ║ └╥┘┌─┐
q_2: ──────────┤ X ├─╫──╫─┤M├
└───┘ ║ ║ └╥┘
c: 3/════════════════╩══╩══╩═
0 1 2
プログラムを実行するためにtargetを選択してください
IonQ シミュレーターで実行する
実際のハードウェアで実行する前に、シミュレーターで回線をテストしてみましょう。 get_backend
を使用して、IonQ シミュレーター バックエンドに接続するBackend
オブジェクトを作成します。
simulator_backend = provider.get_backend("ionq.simulator")
IonQ バックエンドでは、ハードウェアで最適に実行されるようにコンパイルされている定義されたゲートセットのゲートがサポートされています。 このリストにないゲートが回線に含まれている場合は、Qiskit によって提供されるgateset
関数を使用して、サポートされているtranspile
にトランスパイルする必要があります。
from qiskit import transpile
circuit = transpile(circuit, simulator_backend)
トランスパイル関数は、ゲートが、指定されたバックエンドでサポートされているゲートに分解される新しい回線オブジェクトを返します。
これで、Azure Quantum サービスを使用してプログラムを実行し、結果を取得できます。 次のセルは、100 ショットで回路を実行するジョブを送信します。
job = simulator_backend.run(circuit, shots=8)
job_id = job.id()
print("Job id", job_id)
Job id 00000000-0000-0000-0000-000000000000
ジョブが完了するまで待って結果を返すには、次のように実行します。
result = job.result()
print(result)
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='00000000-0000-0000-0000-000000000000', success=True, results=[ExperimentResult(shots=8, success=True, meas_level=2, data=ExperimentResultData(counts={'000': 4, '111': 4}, memory=['000', '000', '000', '000', '111', '111', '111', '111'], probabilities={'000': 0.5, '111': 0.5}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits=3, metadata={}), status=JobStatus.DONE, name='Qiskit Sample - 3-qubit GHZ circuit')], date=None, status=None, header=None, error_data=None)
この結果は Qiskit パッケージにネイティブなオブジェクトであるため、Qiskit の result.get_counts
と plot_histogram
を使用して結果を視覚化できます。 可能性のあるすべてのビット文字列ラベルが表示されるようにするには、それらを counts
に追加します。
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
{'000': 4, '001': 0, '010': 0, '011': 0, '100': 0, '101': 0, '110': 0, '111': 4}
get_memory()
関数を使用して、ジョブの個々のショット データを表示することもできます。
result.get_memory(circuit)
['000', '000', '000', '000', '111', '111', '111', '111']
Note
IonQ targets では、奇数のショットを含むジョブを送信すると、結果は次の偶数に切り捨てられます。 たとえば、9 ショットを指定した場合、結果には 8 ショットのデータが表示されます。
作業コストを見積もる
QPU でジョブを実行する前に、実行するコストを見積もる必要があります。
最新の価格の詳細については、IonQ の価格に関するページを参照するか、またはワークスペースを見つけ、そのワークスペースの [プロバイダー] タブで aka.ms/aq/myworkspaces を使用して価格オプションを表示してください。
IonQ の QPU で実行する
実際のハードウェア ( Quantum Processor Unit (QPU) に接続するには、 target"ionq.qpu.aria-1"
の名前を get_backend
メソッドに指定するだけです。
qpu_backend = provider.get_backend("ionq.qpu.aria-1")
Azure Quantum で実行する回線を送信し、結果を取得し、 plot_histogram
実行して結果をプロットします。
注記
QPU で回路を実行するために必要な時間は、現在のキュー時間によって異なる場合があります。
# Submit the circuit to run on Azure Quantum
job = qpu_backend.run(circuit, shots=100)
job_id = job.id()
print("Job id", job_id)
# Get the job results (this method waits for the Job to complete):
result = job.result()
print(result)
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
Job id 00000000-0000-0000-0000-000000000000
Job Status: job has successfully run
Result(backend_name='ionq.qpu.aria-1', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='00000000-0000-0000-0000-000000000000', success=True, results=[ExperimentResult(shots=1024, success=True, meas_level=2, data=ExperimentResultData(counts={'0': 505, '1': 6, '2': 1, '3': 1, '4': 1, '5': 10, '6': 11, '7': 488}, probabilities={'0': 0.4932, '1': 0.0059, '2': 0.001, '3': 0.001, '4': 0.001, '5': 0.0098, '6': 0.0117, '7': 0.4766}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])
{'000': 505, '001': 6, '010': 1, '011': 1, '100': 1, '101': 10, '110': 11, '111': 488}
重要
1 つのジョブで複数の回路を送信することは現在サポートされていません。 回避策として、backend.run
メソッドを呼び出して各回路を非同期に送信し、その後、各ジョブの結果を取得できます。 次に例を示します。
jobs = []
for circuit in circuits:
jobs.append(backend.run(circuit, shots=N))
results = []
for job in jobs:
results.append(job.result())
前提条件
- アクティブなサブスクリプションが含まれる Azure アカウント。 Azure アカウントをお持ちでない場合は、無料で登録し、 従って支払うサブスクリプションにサインアップしてください。
- Azure Quantum ワークスペース。 詳細については、「Azure Quantum ワークスペースを作成する」を参照してください。
ワークスペースに新しいノートブックを作成する
- Azure portal にログインし、前の手順で作成した新しいワークスペースを選択します。
- 左側のブレードで、[ノートブック] を選択します。
- [マイ ノートブック] をクリックし、[新規追加] をクリックします。
- ファイルの名前 (Qiskit.ipynb など) を入力し、[ファイルの作成] をクリックします。
新しいノートブックを開くと、サブスクリプションとワークスペースの情報に基づいて、最初のセルのコードが自動的に作成されます。
from azure.quantum import Workspace
workspace = Workspace (
resource_id = "", # Add your resource_id
location = "" # Add your workspace location (for example, "westus")
)
Note
特に記載がない限り、コンパイルの問題が発生しないように、各セルは作成した順序で実行する必要があります。
セルの左側にある三角形の [再生] アイコンをクリックして、このコードを実行します。
必要なインポートを読み込む
まず、追加のモジュールをインポートする必要があります。
[+ コード] をクリックして新しいセルを追加した後、次のコードを追加して実行します。
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram
from azure.quantum.qiskit import AzureQuantumProvider
Azure Quantum サービスに接続する
次に、前のセルのAzureQuantumProvider
オブジェクトを使用してWorkspace
オブジェクトを作成し、Azure Quantum ワークスペースに接続します。 次のコードを使用して新しいセルを追加します。
provider = AzureQuantumProvider(workspace)
単純な回路を定義する
新しいセルに circuit
オブジェクトを作成します。 この例は、単純な量子ランダム ビット ジェネレーターです。 回路を定義して表示するための次のコードを追加します。
# Create a Quantum Circuit acting on the q register
circuit = QuantumCircuit(3, 3)
circuit.name = "Qiskit Sample - 3-qubit GHZ circuit"
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure([0, 1, 2], [0, 1, 2])
# Print out the circuit
circuit.draw()
┌───┐ ┌─┐
q_0: ┤ H ├──■───────┤M├──────
└───┘┌─┴─┐ └╥┘┌─┐
q_1: ─────┤ X ├──■───╫─┤M├───
└───┘┌─┴─┐ ║ └╥┘┌─┐
q_2: ──────────┤ X ├─╫──╫─┤M├
└───┘ ║ ║ └╥┘
c: 3/════════════════╩══╩══╩═
0 1 2
すべてを一覧表示する targets
ワークスペースで使用可能なすべての量子コンピューティング targets (バックエンド) を表示できるようになりました。 新しいセルを追加し、次の行を実行します。
print("This workspace's targets:")
for backend in provider.backends():
print("- " + backend.name())
This workspace's targets:
- ionq.simulator
- ionq.qpu.aria-1
- microsoft.estimator
- quantinuum.qpu.h1-1
- quantinuum.sim.h1-1sc
- quantinuum.sim.h1-1e
- rigetti.sim.qvm
- rigetti.qpu.ankaa-3
target を選択してプログラムを実行する
実際の量子ハードウェアで実行する前にコードを確認するには、IonQ 量子シミュレーター ionq.simulator
を使用できます。
新しいセルを追加し、IonQ 量子シミュレーター targetを表すオブジェクトを作成します。
# Get IonQ quantum simulator target:
simulator_backend = provider.get_backend("ionq.simulator")
IonQ シミュレーターで実行する
回路をシミュレーターで実行するには、次のコードを追加します。 この例では、run
の target メソッドを使用してジョブを送信し、ジョブの状態を監視します。
# Submit the circuit to run on Azure Quantum
job = simulator_backend.run(circuit, shots=8)
job_id = job.id()
print("Job id", job_id)
ジョブが正常に実行されたら、ジョブの結果を取得して表示します。
# Get the job results:
result = job.result()
print(result)
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='00000000-0000-0000-0000-000000000000', success=True, results=[ExperimentResult(shots=8, success=True, meas_level=2, data=ExperimentResultData(counts={'000': 4, '111': 4}, memory=['000', '000', '000', '000', '111', '111', '111', '111'], probabilities={'000': 0.5, '111': 0.5}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits=3, metadata={}), status=JobStatus.DONE, name='Qiskit Sample - 3-qubit GHZ circuit')], date=None, status=None, header=None, error_data=None)
この result
型は Qiskit パッケージにネイティブなオブジェクトであるため、Qiskit の result.get_counts
と plot_histogram
を使用して結果を視覚化できます。 可能性のあるすべてのビット文字列ラベルが表示されるようにするには、それらを counts
に追加します。
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
{'000': 4, '001': 0, '010': 0, '011': 0, '100': 0, '101': 0, '110': 0, '111': 4}
get_memory()
関数を使用して、ジョブの個々のショット データを表示することもできます。
result.get_memory(circuit)
['000', '000', '000', '000', '111', '111', '111', '111']
メモ
IonQ targets では、奇数のショットを含むジョブを送信すると、結果は次の偶数に切り捨てられます。 たとえば、9 ショットを指定した場合、結果には 8 ショットのデータが表示されます。
作業コストの見積もり
実際の量子ハードウェアまたは 量子処理装置 (QPU) でジョブを実行する前に、実行するコストを見積もる必要があります。
最新の価格の詳細については、IonQ の価格に関するページを参照するか、またはワークスペースを見つけて、ワークスペースの [プロバイダー] ブレードで価格オプションを表示してください。
IonQ の QPU で実行する
IonQ シミュレーターでジョブを正常に実行し、QPU コストを見積もったら、次にハードウェアで回線を実行します。
注
QPU で回路を実行するために必要な時間は、現在のキュー時間によって異なります。 ワークスペースのプロバイダーブレードを選択すると、targetの平均キュー時間を表示できます。
前に API 検証コントロールで使用したのと同じ run
メソッドおよび演算を使用して、ジョブを送信して監視します。
# Submit the circuit to run on Azure Quantum
job = qpu_backend.run(circuit, shots=100)
job_id = job.id()
print("Job id", job_id)
ジョブが完了したら、以前と同様にジョブの結果を取得し、グラフに表示します。
result = job.result()
print(result)
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
Job id 910b5ac8-98cd-11ec-b3ba-00155d5528cf
Job Status: job has successfully run
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='Job id 54e8c740-98d9-11ec-b382-00155d957f5d', success=True, results=[ExperimentResult(shots=1024, success=True, meas_level=2, data=ExperimentResultData(counts={'0': 505, '1': 6, '2': 1, '3': 1, '4': 1, '5': 10, '6': 11, '7': 488}, probabilities={'0': 0.4932, '1': 0.0059, '2': 0.001, '3': 0.001, '4': 0.001, '5': 0.0098, '6': 0.0117, '7': 0.4766}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])
{'000': 505, '001': 6, '010': 1, '011': 1, '100': 1, '101': 10, '110': 11, '111': 488}
重要
1 つのジョブで複数の回路を送信することは現在サポートされていません。 回避策として、backend.run
メソッドを呼び出して各回路を非同期に送信し、その後、各ジョブの結果を取得できます。 次に例を示します。
jobs = []
for circuit in circuits:
jobs.append(backend.run(circuit, shots=N))
results = []
for job in jobs:
results.append(job.result())
前提条件
インストールについての詳細は、 QDK 拡張機能を設定するを参照してください。
Python と Pip がインストールされた Python 環境。
Azure Quantum Development Kit および Python 拡張機能がインストールされている VS Code。
qsharp
タグとPython タグを含む Azure Quantumqiskit
widget
パッケージ。python pip install "qsharp[qiskit,widgets]>=1.9"
重要
Qiskit の最新バージョンがあることを確認します。 詳細については、「 azure-quantum Python パッケージの更新を参照してください。
基本回線を実行する
VS Code で新しい Python ファイルを開き、Qsharp パッケージの組み込みのスパース シミュレーターを使用して基本回線を定義して実行します。
# load the required imports
from qiskit.circuit.random import random_circuit
from qsharp.interop.qiskit import QSharpBackend
# define and display the circuit
circuit = random_circuit(2, 2, measure=True)
print(circuit)
# run the circuit using the built-in sparse simulator
backend = QSharpBackend()
job = backend.run(circuit)
counts = job.result().get_counts()
print(counts)
プログラムを実行するには、右上にある [実行] アイコンを選択し、 Run Python ファイルを選択します。 出力が新しいターミナル ウィンドウに表示されます。
┌─────────────────────────┐┌─┐
q_0: ─■───────────┤0 ├┤M├───
│P(0.79983) │ (XX-YY)(1.9337,1.7385) │└╥┘┌─┐
q_1: ─■───────────┤1 ├─╫─┤M├
└─────────────────────────┘ ║ └╥┘
c: 2/═════════════════════════════════════════╩══╩═
0 1
{'11': 680, '00': 344}
回線の QIR を生成する
同じ回線を使用して、量子ハードウェア上で実行するために使用される QIR を生成できます。
注記
QIR を生成するときは、すべてのレジスタを測定する必要があります。 未使用のレジスタがある場合は、エラーが発生します。 さらに、プロファイルが Unrestricted
に設定されているときに QIR を生成しようとすると、エラーが発生します。 Unrestricted
プロファイルはシミュレーションでのみ有効です。 TargetProfile.Base または TargetProfile.Adaptive_RI
を使用する必要があります。 target_profile
は、プロファイルを切り替える backend.qir(...)
呼び出しでオーバーライドできます。
QSharpError
とTargetProfile
をインポートするfrom qsharp import QSharpError, TargetProfile
出力を変更して QIR を生成する
print(backend.qir(circuit, target_profile=TargetProfile.Adaptive_RI))
コードは次のようになっているはずです。
# load the required imports
from qiskit.circuit.random import random_circuit
from qsharp.interop.qiskit import QSharpBackend
from qsharp import QSharpError, TargetProfile
# define and display the circuit
circuit = random_circuit(2, 2, measure=True)
print(circuit)
# generate QIR for the circuit
print(backend.qir(circuit, target_profile=TargetProfile.Adaptive_RI))
出力結果:
┌────────────┐ ┌─┐
q_0: ┤ Rx(2.7195) ├─■───────────┤M├───
└──┬─────┬───┘ │U1(5.5924) └╥┘┌─┐
q_1: ───┤ Tdg ├─────■────────────╫─┤M├
└─────┘ ║ └╥┘
c: 2/════════════════════════════╩══╩═
0 1
%Result = type opaque
%Qubit = type opaque
define void @ENTRYPOINT__main() #0 {
block_0:
call void @__quantum__qis__rx__body(double 2.7194945105768586, %Qubit* inttoptr (i64 0 to %Qubit*))
call void @__quantum__qis__rz__body(double 2.796204066686262, %Qubit* inttoptr (i64 0 to %Qubit*))
call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__rz__body(double -2.796204066686262, %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__rz__body(double 2.796204066686262, %Qubit* inttoptr (i64 1 to %Qubit*))
call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
call void @__quantum__rt__array_record_output(i64 2, i8* null)
call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
ret void
}
declare void @__quantum__qis__rx__body(double, %Qubit*)
declare void @__quantum__qis__rz__body(double, %Qubit*)
declare void @__quantum__qis__t__adj(%Qubit*)
declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
declare void @__quantum__rt__array_record_output(i64, i8*)
declare void @__quantum__rt__result_record_output(%Result*, i8*)
attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
attributes #1 = { "irreversible" }
; module flags
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}
!0 = !{i32 1, !"qir_major_version", i32 1}
!1 = !{i32 7, !"qir_minor_version", i32 0}
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
!3 = !{i32 1, !"dynamic_result_management", i1 false}
!4 = !{i32 1, !"classical_ints", i1 true}
!5 = !{i32 1, !"qubit_resetting", i1 true}
!6 = !{i32 1, !"classical_floats", i1 false}
!7 = !{i32 1, !"backwards_branching", i1 false}
!8 = !{i32 1, !"classical_fixed_points", i1 false}
!9 = !{i32 1, !"user_functions", i1 false}
!10 = !{i32 1, !"multiple_target_branching", i1 false}
すべてのプログラムをすべてのハードウェアで実行できるわけではありません。 ここでは target を Base
プロファイルで試すことができますが、プログラムのどの部分がサポートされていないのかについての詳細なエラー情報が表示されます。
try:
backend.qir(qc, target_profile=TargetProfile.Base)
except QSharpError as e:
print(e)