Pennylane-braket
Pennylane-braket は、Pennylane SDK からAmazon braket 上のマシンを呼び出せるプラグインです。
Amazon braket 上には量子コンピュータ実機もありますが、実機の場合は結果がすぐ帰ってこず順番待ちとなります。
この場合、タスクはQueueに積まれた状態となり、後で回収が必要です。
braket単体の場合はチュートリアルに回収の仕方が書いてありますが、Pennylaneから操作した場合にどうしたら良いのかは書いていません。
ずっと、できないと思っていました。
結論から言えばとても簡単なのですが、つまずいたので書いておきます。
code
braket単体の場合のチュートリアルを9割コピペして、以下の関数を作っておきます。
タスクidを与えて、タスクを取ってきて、ヒストグラムプロットします。
def Retrieve_task(task_id):
from braket.aws import AwsQuantumTask
# recover task
task_load = AwsQuantumTask(arn=task_id)
# print status
status = task_load.state()
print('Status of (reconstructed) task:', status)
print('\n')
# wait for job to complete
# terminal_states = ['COMPLETED', 'FAILED', 'CANCELLED']
if status == 'COMPLETED':
# get results
results = task_load.result()
# print(rigetti_results)
# get all metadata of submitted task
metadata = task_load.metadata()
# example for metadata
shots = metadata['shots']
machine = metadata['deviceArn']
# print example metadata
print("{} shots taken on machine {}.\n".format(shots, machine))
# get measurement counts
counts = results.measurement_counts
print('Measurement counts:', counts)
# plot results: see effects of noise
plt.bar(counts.keys(), counts.values());
plt.xlabel('bitstrings');
plt.ylabel('counts');
plt.tight_layout();
plt.xticks(rotation=90);
elif status in ['FAILED', 'CANCELLED']:
# print terminal message
print('Your task is in terminal status, but has not completed.')
else:
# print current status
print('Sorry, your task is still being processed and has not been finalized yet.')
出力イメージは以下の通り。
Status of (reconstructed) task: COMPLETED 1024 shots taken on machine arn:aws:braket:::device/qpu/ionq/ionQdevice. Measurement counts: Counter({'0101': 317, '1010': 201, '0110': 91, '1100': 83, '0011': 62, '1001': 54, '0100': 38, '1000': 26, '1110': 24, '0000': 23, '0010': 20, '0001': 20, '1011': 20, '1101': 16, '1111': 16, '0111': 13})
次に、Pennylane経由でタスクを投げるときの注意点です。
Pennylaneはタスクがすぐ返ってくることを期待しますので、Queueに積まれると止まってしまいます。
これを避けるために、タイムアウトを設定する必要があります。(まぁ、無理やり抜けても良いんですが)
また、タスクのidを控えておく必要があります。
そのためには、以下のようにします。
まず、タイムアウト設定です。
以下では3秒としています。
dev_remote_ionq = qml.device(
"braket.aws.qubit",
device_arn=device_arn_ionq,
wires=n_qubits,
s3_destination_folder=s3_folder,
shots = 1024,
poll_timeout_seconds = 3
)
次に、タスクidですが、
タスク(回路)を投げてタイムアウトした後に
ionq_task_id = dev_remote_ionq.task.id
とします。実はdevにはtask属性というものが存在していて、
そのidやstateを呼ぶことができます。ioqやrigettiを使った場合、
ちゃんとこの id はaws上のタスクのidになります。(最も新しいもののidが取られます)
ibmqの場合は確認していないのですが、おそらくibmq上のタスクのidになると思います。
ただしibmqはretrieveのコマンドが違うので、上記関数 Retrieve_task では動きません。
qiskitにtaskを取ってくる関数があるので、それを使ってしまえばいいと思います。
結論
細かいところは自分で埋めるしかなし。。