IBMQ のお試し

量子コンピュータの基本的な使い方のメモです。まず, IBMQ は以下のサイトから利用できます。
IBM Q Experience
簡単な回路であれば, GUI で試してみるのが良いと思います。
ドラッグ&ドロップで簡単に使うことができます。ただし, 使用するバックエンド(ibmqx2, ibmqx4 など)によって回路が異なるため, 制御NOT (CNOT)を使用するときにどのノードにおけるかは制限があります。
f:id:puyokw:20180407170318j:plain
simulate を押せばシミュレーションが実行でき, run を押せば実機で実行できます。

本格的に使いたい場合には, qiskit を使用するのが良さそうです。
GitHub - QISKit/qiskit-sdk-py: Quantum Software Development Kit for writing quantum computing experiments, programs, and applications.
python からibmqを使用することができます。インストールは

pip install qiskit

で, できます。
実機で実行するには, api token が必要となります。
github のinstallation の項に従って, IBM Q Experience のアカウントを作成して, api token を発行します。
(ユーザー名の部分をクリックして, My Account を選択。Advanced の項目の中にAPI Token が存在するので, そこのRegenerate をクリックして作成。)

Qconfig.py として以下のようなコードを準備します。(API token は先程取得したものを記載します。)

APItoken = 'PUT_YOUR_API_TOKEN_HERE'

config = {
    'url': 'https://quantumexperience.ng.bluemix.net/api',

    # If you have access to IBM Q features, you also need to fill the "hub",
    # "group", and "project" details. Replace "None" on the lines below
    # with your details from Quantum Experience, quoting the strings, for
    # example: 'hub': 'my_hub'
    # You will also need to update the 'url' above, pointing it to your custom
    # URL for IBM Q.
    'hub': None,
    'group': None,
    'project': None
}

if 'APItoken' not in locals():
    raise Exception('Please set up your access token. See Qconfig.py.')

これで準備が完了です。
以下では, 具体的に回路を作成して, 回路図の表示, シミュレーションの実行を行います。
f:id:puyokw:20180409035411j:plain
このようなtoy example を考えてみます。
回路自体は次のように書けます。

from qiskit import QuantumProgram
qp = QuantumProgram()

nq = 3  # number of qubits
q = qp.create_quantum_register("q", nq) # nq 量子ビット準備する
c = qp.create_classical_register("c", nq) # 測定用の領域を確保

circuits = ['testQ'] # 回路の名前を入力
testQ = qp.create_circuit(circuits[0], [q], [c]) # 回路の作成準備
# 1 列目
testQ.h(q[0]) # q0 にH を作用させる
testQ.h(q[1]) # q1 にH を作用させる
testQ.h(q[2]) # q2 にH を作用させる

# 2 列目
testQ.z(q[1]) # q1 にz を作用させる
testQ.cx(q[1],q[2]) # q1, q2 にcnotを作用させる

# 3 列目
testQ.h(q[2]) # q2 にH を作用させる

# 測定
testQ.measure(q[0], c[0]) # q0 を測定し, c0 に結果を格納
testQ.measure(q[1], c[1]) # q1 を測定し, c1 に結果を格納
testQ.measure(q[2], c[2]) # q2 を測定し, c2 に結果を格納

これをシミュレーションして, 結果をヒストグラムで表示します。

# 実行する
results = qp.execute(circuits, backend='local_qasm_simulator', shots=8192, seed=1) 
# 結果を図示する
from qiskit.tools.visualization import plot_histogram
plot_histogram(results.get_counts(circuits[0]))

f:id:puyokw:20180409035645p:plain
結果の状態(000や001など)では, 右側からq0, q1, q2 を示しています。この場合q2 は常に0 の状態です。

回路図を表示するのがやや面倒で, まずlatex_drawer を用いることで, tex ファイルに変換します。ここからは各自の環境に依存しますが, pdflatex を用いてpdf に変換して, さらにpdf2image もしくはpoppler のpdftocairo を用いて画像に変換して読み込みます。

import os 
from qiskit.tools.visualization import latex_drawer
from PIL import Image 
# ipython を使用する場合
# from IPython.display import Image 

filename='circuit'
tmpdir='tmp/'
if not os.path.exists(tmpdir):
    os.makedirs(tmpdir)

latex_drawer(testQ, tmpdir+filename+".tex", basis="h,z") # tex ファイルの作成
os.system("pdflatex -output-directory {} {}".format(tmpdir, filename+".tex")) # tex -> pdf 
os.system("pdftocairo -jpeg {}.pdf {}".format(tmpdir+filename, tmpdir+filename)) # pdf -> jpeg
img = Image.open(os.path.join('./'+tmpdir+filename+'-1.jpg'))
img.show()
#Image(filename=os.path.join(tmpdir+filename+'-1.jpg')) # ipython を使用する場合
#pdf2image.convert_from_path(tmpdir+filename+".pdf") # pdf2image が使える場合は, こちらでもOK 

上記のようなコードにより, 回路図が表示されます。
sympy のqasm を用いても回路図を表示できます。まず, 回路のコードを表示します。

QASM_source = qp.get_qasm('testQ')
print(QASM_source)
#OPENQASM 2.0;
#include "qelib1.inc";
#qreg q[3];
#creg c[3];
#h q[0];
#h q[1];
#h q[2];
#z q[1];
#cx q[1],q[2];
#h q[2];
#measure q[0] -> c[0];
#measure q[1] -> c[1];
#measure q[2] -> c[2];

次に, plot するために文字列を変換していきます。

from sympy.physics.quantum.qasm import Qasm

STR=str(QASM_source).replace(';','').replace('[','').replace(']','').replace('cx','cnot').split('\n')[4:-1]
SSTR=[]
for s in STR:
    s_tmp=s.split(' ')
    if s_tmp[0]=='measure':
        s_tmp=s_tmp[:-2]
    s_tmp2=s_tmp[0]
    if len(s_tmp)>1:
        s_tmp2+=' '
        s_tmp2+=','.join(s_tmp[1::])
    SSTR.append(s_tmp2)

SSTR=["qubit "+"q"+str(i) for i in range(nq)]+SSTR
print(SSTR)
# ['qubit q0', 'qubit q1', 'qubit q2', 'h q0', 'h q1', 'h q2', 'z q1', 'cnot q1,q2', 'h q2', 'measure q0', 'measure q1', 'measure q2'] 

これを用いて図示します。

import matplotlib.pyplot as plt
qprog1=Qasm()
for i in range(len(SSTR)):
    qprog1.add(SSTR[i])

qprog1.plot()
plt.show()

f:id:puyokw:20180409040419p:plain

他にも, 実機で実行する場合などのチュートリアルが以下に書かれています。
GitHub - QISKit/qiskit-tutorial: A collection of Jupyter notebooks using QISKit

python から実機での実行がまだ上手く行っていないので, そのあたりをもう少し調べていこうと思います。