<jupyter_start><jupyter_text>0. 今日の量子コンピュータの問題- Noisy Intermediate-Scale Quantum (NISQ) デバイス    - 量子回路が深くなる（ゲート数が多くなる）ほど、誤差が大きくなる    - 十分な量子ビット数ではない- 量子ビットが全結合でない量子デバイスもある- 各社が開発している量子デバイスに対して、量子ソフトウェアツールキットが用意されてる  0-1. TKETとは- Quantum Software Development Kit- C++で実装- pythonモジュール　`pytket`で利用可能- 最適化コンパイラ：　ユーザーフレンドリーな回路→量子デバイスで実行可能な回路に変換可能    - Language-agnostic (多くの量子回路をプログラミングするフレームワーク(qiskit, Cirq, etc)をサポート)    - Retagetable (多くの量子デバイス(IBM, Honeywell, etc)をサポート)    - Circuit Optimisation (量子計算時に生じるデバイスエラーの影響を最小化。デバイス依存＆デバイス非依存のものが実装)     参照- [pytket ドキュメント](https://cqcl.github.io/tket/pytket/api/index.html)- [pytket ユーザーマニュアル](https://cqcl.github.io/pytket/manual/index.html)- [t|ket⟩ : A Retargetable Compiler for NISQ Devices](https://arxiv.org/abs/2003.10611)  0-2. 今回必要となる python、python パッケージ* Python 3.7 or higher (Python 3.9.7で動作確認をしています。)|  パッケージ （version） |  概要  || :---- | :---- ||  pytket==0.19.2  |  tketを利用するためのpython モジュール ||  pytket-qiskit==0.22.0  |  qiskitを利用するためのpytket-extension  ||  pytket-braket==0.16.0  |  Amazon Braketを利用するためのpytket-extension  ||  pytket-qsharp==0.21.0  |  Azure Quantumを利用するためのpytket-extension  ||  pytket-qulacs==0.16.0  |  Qulacsを利用するためのpytket-extension  |* pytket-qsharpのパッケージは.net等のインストールが必要です。詳しくは[pytket-qsharpドキュメント](https://cqcl.github.io/pytket-extensions/api/qsharp/index.htmlhttp://)をご確認ください。 環境にインストールされていない場合は、以下のセルの＃を取り除き、インストールしてください。<jupyter_code>#!pip install pytket==0.19.2
#!pip install pytket-qiskit==0.22.0
#!pip install pytket-braket==0.16.0
#!pip install pytket-qsharp==0.21.0
#!pip install pytket-qulacs==0.16.0
#!pip install pylatexenc #可視化のためのパッケージ<jupyter_output><empty_output><jupyter_text>1. 量子回路を作成ここでは IBMの量子デバイスやシュミレーションを利用できる`qiskit`と`tket`でベル状態を作成する。  1-1. `qiskit`でベル状態を作成$$ |\Psi\rangle = \frac{1}{\sqrt{2}}(|00\rangle+|11\rangle)$$<jupyter_code>from qiskit import QuantumCircuit

qs_bell = QuantumCircuit(2)
qs_bell.h(0)
qs_bell.cx(0,1)
qs_bell.measure_all()

qs_bell.draw(output='mpl')
#from qiskit.tools.visualization import circuit_drawer
#circuit_drawer(qs_bell, output='mpl')<jupyter_output><empty_output><jupyter_text>1-2. IBMが提供しているローカルシミュレータで計算<jupyter_code>from qiskit import Aer
from qiskit.visualization import plot_histogram
#Aer.backends()
ibm_sim = Aer.get_backend('aer_simulator')
handle = ibm_sim.run(qs_bell, shots=1000)
counts = handle.result().get_counts()
plot_histogram(counts)<jupyter_output><empty_output><jupyter_text>1-3. `tket`でベル状態を作成<jupyter_code>from pytket import Circuit
from pytket.circuit.display import render_circuit_jupyter

bell = Circuit(2)
bell.H(0).CX(0,1)
bell.measure_all()

render_circuit_jupyter(bell)<jupyter_output><empty_output><jupyter_text>1-4. `pytket-qiskit`でIBMが提供しているローカルシミュレータで計算<jupyter_code>from pytket.extensions.qiskit import AerBackend
backend = AerBackend()

handle = backend.process_circuit(bell, n_shots =1000)
result_counts = backend.get_result(handle).get_counts()
plot_histogram(result_counts)<jupyter_output><empty_output><jupyter_text>2. 量子回路の変換pytketでは- qiskitで記述した量子回路からtketの量子回路のクラスに変換が可能- tketで記述した量子回路からqiskitの量子回路のクラスに変換が可能- tketで記述した量子回路と他の量子回路をプログラミングするフレームワークでの量子回路の交換が可能参照：[pytket-extensions](https://cqcl.github.io/pytket-extensions/api/index.html)   2-1. `qiskit`の量子回路から`tket`の量子回路に変換<jupyter_code>from pytket.extensions.qiskit import qiskit_to_tk
bell2 = qiskit_to_tk(qs_bell)
bell2
render_circuit_jupyter(bell2)<jupyter_output><empty_output><jupyter_text>2-2. `tket`の量子回路から`qiskit`の量子回路に変換<jupyter_code>from pytket.extensions.qiskit import tk_to_qiskit
qs_bell2 = tk_to_qiskit(bell)
qs_bell2.draw('mpl')
#from pytket.extensions.braket import tk_to_braket
#tk_to_braket(bell)<jupyter_output><empty_output><jupyter_text>3. 量子回路の最適化例えば、Hゲートを同じビットに連続して作用させるとゲート操作をしていない恒等な量子状態が得られます。量子回路が深くなる（ゲート数が多くなる）ほど、誤差が大きくなるNISQ デバイスでは左辺のような状況は除去したい。その他にも下記のような恒等な関係があります。  3-1. PauliSimp 関数を利用した、量子回路の最適化tketには量子回路を最適化する様々な機能が用意されている。ここでは、PauliSimp 関数を利用した回路の最適化を行う。（PauliSimp 関数：Pauli ゲートとCliffordゲートで表現された量子回路を出力）ランダムな量子回路を作成し、回路の深さとCXの深さを数える。<jupyter_code>from pytket.pauli import Pauli
from pytket.circuit import PauliExpBox, fresh_symbol, OpType
from pytket.passes import DecomposeBoxes
box = PauliExpBox([Pauli.I, Pauli.Z, Pauli.X, Pauli.Y], fresh_symbol('tm'))
from pytket.utils import Graph
import numpy as np

def get_random_pauli_gadgets(n_qubits, n_pauli_gadgets, max_entangle):
    """ """
    paulis = [Pauli.I, Pauli.X, Pauli.Y, Pauli.Z]
    circ = Circuit(n_qubits)
    for i in range(n_pauli_gadgets):
        ls_paulis = [np.random.choice(paulis) for k in range(max_entangle)]
        if ls_paulis.count(Pauli.Y) % 2 == 0:
            continue
        if len(ls_paulis) - ls_paulis.count(Pauli.I) <= 1:
            continue
        qubits = np.random.choice(
            [i for i in range(n_qubits)], size=max_entangle, replace=False
        )
        box = PauliExpBox(ls_paulis, fresh_symbol('a'))
        circ.add_pauliexpbox(box, sorted(qubits))
    DecomposeBoxes().apply(circ)
    return circ

circ = get_random_pauli_gadgets(
    n_qubits=8, n_pauli_gadgets=300, max_entangle=5
)
print('Circuit depth: ', circ.depth())
print('CX depth: ', circ.depth_by_type(OpType.CX))
render_circuit_jupyter(circ)<jupyter_output><empty_output><jupyter_text>PauliSimp 関数を使って、量子回路の最適化<jupyter_code># Circuit optimization by using compiler passes.
from pytket.passes import PauliSimp
circx = circ.copy()
PauliSimp().apply(circx)
print('Circuit depth: ', circx.depth())
print('CX depth: ', circx.depth_by_type(OpType.CX))
#render_circuit_jupyter(circx)<jupyter_output><empty_output><jupyter_text>4. pytket-extensionで、IBM Quantum、Amazon Braket、Azure Quantum、Qulacsを利用- 下記のスクリプトはそれぞれのクラウドで有料の操作となることがありますので、ご注意ください  4-1. pytket-qiskitを利用して、IBM Quantumのシミュレータや実機にアクセス<jupyter_code>path = 'ibm-token'
f = open(path)
ibm_token = f.read()
f.close()
from pytket.extensions.qiskit.backends.config import set_ibmq_config
set_ibmq_config(ibmq_api_token=ibm_token)
from pytket.extensions.qiskit import IBMQBackend, IBMQEmulatorBackend
from pytket import Circuit
from pytket.circuit.display import render_circuit_jupyter
#ibm_backend = IBMQBackend("ibmq_lima")
#ibm_backend = IBMQBackend("ibmq_qasm_simulator")
# AerBackend to emulate the behaviour of IBMQBackend. Requires a valid IBMQ account.
ibm_backend = IBMQEmulatorBackend("ibmq_lima")
bell = Circuit(2)
bell.H(0).CX(0,1)
bell.measure_all()
render_circuit_jupyter(bell)

# backendのgate setで量子回路を表現する
ibm_backend.compile_circuit(bell)
render_circuit_jupyter(bell)
ibm_handle = ibm_backend.process_circuit(bell, n_shots =1000)
ibm_result = ibm_backend.get_result(ibm_handle)
#ibm_backend.cancel(ibm_handle)
from qiskit.visualization import plot_histogram
plot_histogram(ibm_result.get_counts())<jupyter_output><empty_output><jupyter_text>4-2. pytket-braketを利用して、Amazon Braketのシミュレータや実機にアクセス<jupyter_code>#フォルダーにアクセスキー等の情報ファイルaws-keyを作成し、読み込む
path = 'aws-key'
f = open(path)
aws_access_key_id, aws_secret_access_key, s3_name, bucket_key= [s.strip() for s in f.readlines()]
f.close()
# Braket clientを作成し、Sessionを開始
import boto3
from braket.aws import AwsSession
boto_session = boto3.Session(
    aws_access_key_id= aws_access_key_id,
    aws_secret_access_key= aws_secret_access_key,
    region_name= 'us-west-1'
)
aws_session = AwsSession(boto_session=boto_session)
#aws_session.search_devices()
# backend の選択
from pytket.extensions.braket import BraketBackend

# ionQ   arn:aws:braket:::device/qpu/ionq/ionQdevice, region: us-east-1
# aws_backend = BraketBackend(device='ionQdevice', s3_bucket=s3_name , s3_folder = bucket_key, device_type = 'qpu', provider = 'ionq', aws_session=aws_session)
# Aspen-11   arn:aws:braket:::device/qpu/rigetti/Aspen-11 #Aspen-11, region: us-west-1
# aws_backend = BraketBackend(device='Aspen-11', s3_bucket=s3_name , s3_folder = bucket_key, device_type = 'qpu', provider = 'rigetti', aws_session=aws_session)
# SV1    sim_arn = 'arn:aws:braket:::device/quantum-simulator/amazon/sv1'     #SV1, region:
aws_backend = BraketBackend(device='sv1', s3_bucket=s3_name , s3_folder = bucket_key, aws_session=aws_session)
# TN1   sim_arn = 'arn:aws:braket:::device/quantum-simulator/amazon/tn1'    #TN1, region: us-west-2, us-east-1
# aws_backend = BraketBackend(device='tn1', s3_bucket=s3_name , s3_folder = bucket_key, device_type = 'quantum-simulator', provider = 'amazon', aws_session=aws_session)
# DM1   'arn:aws:braket:::device/quantum-simulator/amazon/dm1'    #DM1, region: 
# aws_backend = BraketBackend(device='dm1', s3_bucket=s3_name , s3_folder = bucket_key, device_type = 'quantum-simulator', provider = 'amazon', aws_session=aws_session)

# bell状態の作成
bell = Circuit(2)
bell.H(0).CX(0,1)
render_circuit_jupyter(bell)

# backendのgate setで量子回路を表現する
aws_backend.compile_circuit(bell)
render_circuit_jupyter(bell)
aws_handle = aws_backend.process_circuit(bell, n_shots =1000)
aws_result = aws_backend.get_result(aws_handle)
print(aws_result.get_counts())
counts = aws_result.get_counts()
plot_histogram(counts)<jupyter_output><empty_output><jupyter_text>4-3. pytket-qsharpを利用して、Azure Quantumのシミュレータや実機にアクセス<jupyter_code>path = 'azure-key'
f = open(path)
resource_id = [s.strip() for s in f.readlines()]
f.close()
from pytket.extensions.qsharp import set_azure_config
set_azure_config(resourceId=resource_id, location="eastus")
from pytket.extensions.qsharp import AzureBackend
# Azure Qauntum上の実機IonQを利用する
# from pytket.extensions.qsharp import AzureBackend
# azure_backend = AzureBackend(target_name='ionq.simulator')
# Azure Qauntumが提供しているローカルシミュレータを利用する
from pytket.extensions.qsharp import QsharpSimulatorBackend
from qiskit.visualization import plot_histogram
azure_backend = QsharpSimulatorBackend()
from pytket import Circuit
from pytket.circuit.display import render_circuit_jupyter
bell = Circuit(2)
bell.H(0).CX(0,1)
bell.measure_all()
render_circuit_jupyter(bell)

# backendのgate setで量子回路を表現する
azure_backend.compile_circuit(bell)
render_circuit_jupyter(bell)
result = azure_backend.process_circuit(bell, n_shots=1000)
azure_result = azure_backend.get_result(result)
azure_counts = azure_result.get_counts()
azure_counts
plot_histogram(azure_counts)<jupyter_output><empty_output><jupyter_text>4-4. pytket-qulacs を利用して、Qulacsのシミュレータにアクセス<jupyter_code>from pytket.extensions.qulacs import QulacsBackend
qulacs_backend = QulacsBackend()
# bell状態の作成
bell = Circuit(2)
bell.H(0).CX(0,1)
bell.measure_all()

render_circuit_jupyter(bell)

# backendのgate setで量子回路を表現する
qulacs_backend.compile_circuit(bell)
render_circuit_jupyter(bell)
qulacs_handle = qulacs_backend.process_circuit(bell, n_shots=1000)
qulacs_result = qulacs_backend.get_result(qulacs_handle)
print(qulacs_result.get_counts())
counts = qulacs_result.get_counts()
plot_histogram(counts)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11511194029850746, 'fraction_numerical': 0.018190298507462687, 'mean_word_length': 7.4885193982581155, 'pattern_counts': {'":': 0, '<': 54, '<?xml version=': 0, '>': 53, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '92025', 'license': 'Apache-2.0', 'n_tokens_mistral': 5197, 'n_tokens_neox': 4955, 'n_words': 592, 'path': 'materials/2022-02-24/20220224.ipynb', 'repo_name': 'cqcjapan/tket-workshop', 'size': '10720'}