BlueqatでCirqバックエンドをつくってみた
はじめに
年末恒例のアドベントカレンダーで量子コンピュータ関連の記事がたくさんアップされていて、2019年のまとめのような感じもしてとても参考になります。今回は、アドベントカレンダーで見つけた記事を参考にBlueqatのバックエンドをつくってみたいと思います。
Blueqatの開発者であるgyu-donさんの記事です。
qiita.com
この記事ではIBMのQiskitのバックエンドの実装方法が紹介されていますが、ここではGoogleのCirqを利用するバックエンドを作ります。
Cirqでの回路形式
参考記事によると量子回路をOpenQASM形式で入力できる場合、簡単にBlueqatバックエンドを作れようです。そこで、Cirqの公式ドキュメントを読むとOpenQASMの入力を受け入れるメソッドcircuit_from_qasm
が用意されていることがわかります。これを使えばさっくりバックエンドが作れそうです。
バックエンドをつくる
基本は参考にした記事のとおりです。
テストにを出力する2ビットのGrover回路を仕様します。
過去にCirqでGroverのアルゴリズムを実装したヤツの使いまわしです。
sjsy.hatenablog.com
ではコードです。
まずは、必要なパッケージのインポート
import warnings import collections from collections import Counter import blueqat from blueqat import Circuit from blueqat import BlueqatGlobalSetting blueqat.__version__
'0.3.11-dev'
バックエンド作成機能があるBlueqatをインストールしてます。
def _qasm_runner_cirq(qasm, shots=None, returns=None, **kwargs): if returns is None: returns = "cirq_result" elif returns not in ("cirq_result", 'draw'): raise ValueError("`returns` shall be None, 'draw', 'cirq_result' or '_exception'") import_error = None try: with warnings.catch_warnings(): from cirq import Circuit, Simulator from cirq.contrib.qasm_import import circuit_from_qasm import cirq except Exception as e: import_error = e if import_error: if returns == "_exception": return e if isinstance(import_error, ImportError): raise ImportError("Cannot import Cirq. To use this backend, please install qiskit." + " `pip install Cirq`.") else: raise ValueError("Unknown error raised when importing Cirq. To get exception, " + 'run this backend with arg `returns="_exception"`') else: if returns == "_exception": return None cirq_circuit = circuit_from_qasm(qasm) if returns == "draw": return cirq_circuit if shots is None: shots = 1024 simulator = cirq.Simulator() result = simulator.run(cirq_circuit, repetitions=shots, **kwargs) if returns == "cirq_result": return result return result cirq_backend = blueqat.backends.qasm_parser_backend_generator.generate_backend(_qasm_runner_cirq) BlueqatGlobalSetting.register_backend("mycirq", cirq_backend)
参考にした記事のコードをベースにCirqで実行できるように書き換えています。returns
で返す出力結果は改良の余地がありあそうですが、まずはシンプルに作りました。
作ったバックエンドをグローバーのアルゴリズムで確認してみます。
# 量子回路初期化 qc = Circuit(2) # オラクル(|11>を反転) qc.h[:].cz[0, 1].h[:] # 振幅増幅 qc.x[:].cz[0, 1].x[:].h[:] # 測定 qc.m[:]
回路の表示
qc.run(returns='draw',shots=10000, backend="mycirq")
q_0: ───H───────@───H───X───@───X───H───M('c_0')───
│ │
q_1: ───I───H───@───H───X───@───X───H───M('c_1')───
Buleqatは回路の表示がないので、回路表示ができるバックエンドは回路確認するのに便利ですね。
量子回路のシミュレーション実行
result = qc.run(shots=10000, backend="mycirq") result.histogram(key=['c_0']) result.histogram(key=['c_1'])
Counter({1: 10000})
Counter({1: 10000})
ちゃんと実行できているようです。
Cirqを使うバックエンドの実装ができました!!! これでQiskitもCirqもBlueqatのバックエンドとして実行できるようになったので、量子回路のコードが書きやすいBlueqatをどんどん利用していきたいと思います!!!他のバックエンドもどんどん作っていきたいですね。