# Qiskitライブラリーを導入
from qiskit import *

# 描画のためのライブラリーを導入
import matplotlib.pyplot as plt
%matplotlib inline

# 数値計算モジュールを導入
import numpy as np

# Qiskitバージョンの確認
qiskit.__qiskit_version__

# 3量子ビット回路を用意
qr = QuantumRegister(3)    
a_0 = ClassicalRegister(1)
a_1 = ClassicalRegister(1)
b_0 = ClassicalRegister(1)

qc = QuantumCircuit(qr,a_0,a_1,b_0)    

# Aliceのもつ未知の量子状態ψをRyで作ります。角度はπ/5にしました。
qc.ry(np.pi/5,0)
qc.barrier()    #回路を見やすくするために入れます

# EveがEPRペアを作ってq1をAliceにq2をBobに渡します
qc.h(1)
qc.cx(1, 2)
qc.barrier()

# AliceがCNOTとHでψと自分のEPRペアをエンタングルさせ測定します。
qc.cx(0, 1)
qc.h(0)
qc.barrier()
qc.measure(0, a_0)
qc.measure(1, a_1)

#Aliceが測定結果をBobに送り、Bobが結果に合わせて操作します
qc.z(2).c_if(a_0, 1)
qc.x(2).c_if(a_1, 1)

# 回路を描画
qc.draw(output="mpl")

# 3量子ビット回路を用意
qr = QuantumRegister(3)    
a_0 = ClassicalRegister(1)
a_1 = ClassicalRegister(1)
b_0 = ClassicalRegister(1)

qc = QuantumCircuit(qr,a_0,a_1,b_0)    

# Aliceのもつ未知の量子状態ψをRyで作ります。角度はπ/5にしました。
qc.ry(np.pi/5,0)
qc.barrier()    #回路を見やすくするために入れます

# EveがEPRペアを作ってq1をAliceにq2をBobに渡します
qc.h(1)
qc.cx(1, 2)
qc.barrier()

# AliceがCNOTとHでψと自分のEPRペアをエンタングルさせ測定します。
qc.cx(0, 1)
qc.h(0)
qc.barrier()
qc.measure(0, a_0)
qc.measure(1, a_1)

#Aliceが測定結果をBobに送り、Bobが結果に合わせて操作します
qc.z(2).c_if(a_0, 1)
qc.x(2).c_if(a_1, 1)

# 未知の量子状態ψの逆ゲートをかけて０が測定できるか確かめます
qc.ry(-np.pi/5, 2)    
qc.measure(2, b_0)

qc.draw(output="mpl")

# qasm_simulatorで実行して確認します
backend = BasicAer.get_backend('qasm_simulator')
counts = execute(qc, backend).result().get_counts()
print(counts)

from qiskit.visualization import plot_histogram
plot_histogram(counts)

# 3量子ビット、1古典ビットの回路を用意
qc = QuantumCircuit(3,1)    

# Aliceのもつ未知の量子状態ψをRyで作ります。角度はπ/5にしました。
qc.ry(np.pi/5,0)
qc.barrier()    #回路を見やすくするために入れます

# EveがEPRペアを作ってq1をAliceにq2をBobに渡します
qc.h(1)
qc.cx(1, 2)
qc.barrier()

# AliceがCNOTとHでψと自分のEPRペアをエンタングルさせます。
qc.cx(0, 1)
qc.h(0)
qc.barrier()

# Aliceの状態に合わせてBobが操作します（ここを変えています！）
qc.cz(0,2)
qc.cx(1,2)

# 未知の量子状態ψの逆ゲートをかけて０が測定できるか確かめます
qc.ry(-np.pi/5, 2)    
qc.measure(2, 0)

qc.draw(output="mpl")

# 先にシミュレーターでコードが合っているか確認します
backend = BasicAer.get_backend('qasm_simulator')
counts = execute(qc, backend).result().get_counts()
print(counts)
plot_histogram(counts)

# 初めて実デバイスで実行する人はこちらを実行
from qiskit import IBMQ
IBMQ.save_account('MY_API_TOKEN')    # ご自分のトークンを入れてください

# アカウント情報をロードして、使える量子デバイスを確認します
IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q')
provider.backends()

# 最もすいているバックエンドを選びます
from qiskit.providers.ibmq import least_busy
large_enough_devices = IBMQ.get_provider().backends(filters=lambda x: x.configuration().n_qubits > 3 and not x.configuration().simulator) 
print(large_enough_devices)
real_backend = least_busy(large_enough_devices)   

print("ベストなバックエンドは " + real_backend.name())

# 上記のバックエンドで実行します
job = execute(qc,real_backend)

# ジョブの実行状態を確認します
from qiskit.tools.monitor import job_monitor
job_monitor(job)

# 結果を確認します
real_result= job.result()
print(real_result.get_counts(qc))
plot_histogram(real_result.get_counts(qc))