Builder構文

# はじめに
Qiskitには、パルスを扱うモジュールが存在しています。そのモジュールに最近ビルダープログラミングモデル(Builder構文)が導入されました。この記事ではその新しいプログラムの書き方を紹介していきたいと思います。

まず、Qiskit Pulseを動かすために必要な記述をまとめておきます。

```Python
import numpy as np
from qiskit import QuantumCircuit, transpile, Aer, IBMQ
from qiskit.visualization import *

IBMQ.load_account()

provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
backend = provider.get_backend('ibmq_armonk')
backend_defaults = backend.defaults()
backend_config = backend.configuration()

```

### 従来の書き方
最初に従来の書き方をみていきたいと思います。対象は1量子ビットです。パルスを定義するためにはScheduleクラスを生成する必要があります。

```Python
from qiskit import pulse
from qiskit.pulse import DriveChannel
from qiskit.pulse import Play
from qiskit.pulse import Schedule

qubit=0

# 1 パルスの定義
drive_pulse = pulse.Gaussian(duration=300,
                             sigma=80,
                             amp=1.0,
                             name='sample gaussian')
# 2 チャネルの指定
drive_chan = pulse.DriveChannel(qubit)

# 3 測定パルスの定義 
inst_sched_map = backend_defaults.instruction_schedule_map
measure = inst_sched_map.get('measure', qubits=backend_config.meas_map[0])

# 4 スケジュールを作成
schedule = pulse.Schedule(name='Sample')
schedule += Play(drive_pulse, drive_chan)
schedule += measure << schedule.duration
```

1. パルスの定義  
実験に使用するパルスを定義します。ここではGaussianパルスの駆動パルスを定義しています。
1. チャネルの指定  
パルスを適用するチャネルを指定します。この例では駆動チャネルを定義しており、これは量子ビットのIDによってインデックス化されます。
1. 測定パルスの定義  
自分で定義することはできますが、ここではバックエンドのデフォルトの命令スケジュールマップからキャリブレーション済みの測定パルスを取得します。
1. スケジュールの作成  
Scheduleクラスを生成し、Playを利用して、駆動パルスを駆動チャネルで動かすことを定義します。その後measureの実行を、スケジュールの開始時刻をある期間だけシフトする`<<` を利用して、Playで定義したパルス分だけシフトして定義しています。



### 新しい書き方(Builder構文)

従来の書き方だと、上記の通り`<<`を利用してパルスの順番を定義するなどプログラム構文を直接処理してパルスのフローを記述しています。これだとプログラム表現（データ）をプログラミング構文（コード）から分離することができていませんでした。

新しい書き方ではPythonのwith構文を利用し、その課題を解決できるようになっています。

```python
from qiskit import pulse

GHz = 1.0e9 # Gigahertz
mem_slot=0
freq_GHz=4.95
freq=freq_GHz*GHz

# 1 Builder構文の定義
with pulse.build(backend) as sample_sched:
    # 2 フローの定義
    with pulse.align_sequential():
        # 3 周波数の定義
        pulse.set_frequency(freq, pulse.drive_channel(qubit))
        pulse.play(pulse.Gaussian(duration=320,
                                  amp=1.0,
                                  sigma=80,
                                  name='sample gaussian'),
                   pulse.drive_channel(qubit))
        # 4 測定パルスの定義
        pulse.measure(qubits=[qubit], registers=[pulse.MemorySlot(mem_slot)])
```

1. Builder構文の定義
Pythonのwith構文を使ってBuilderを定義します。パルスプログラミングを開始するには、最初にビルダー構文を`build()`で初期化する必要があります。

    https://qiskit.org/documentation/stubs/qiskit.pulse.builder.build.html#qiskit.pulse.builder.build

1. フローの定義
ここでは`align_sequential()`を利用してパルスのスケジュールをシーケンシャルに実行するように宣言しています。この場合`align_sequential()`がないと、後続のGaussianパルスとmeasureパルスが同時に実行されることになります。他にも`align_left()`、`align_right()`が提供されており自由に組み合わせることで多彩なパルスのフローを設定することができます。また下記のように`default_alignment`の値を`sequential`とすることでも同じような設定となります。

    ```python
    with pulse.build(backend=backend, default_alignment='sequential', name='sample') as sample_sched:
    ```
1. 周波数の定義
`set_frequency()`を利用して周波数を定義します。
1. 測定パルスの定義
従来の書き方ではバックエンドのデフォルトの命令スケジュールマップからキャリブレーション済みの測定パルスを取得しましたが、この例のように書くことも可能です。アクティブなビルダー構文内の量子ビットを測定します。パルスレベルでは、測定はパルスと、システム測定ユニットにデータを取得して処理するように指示する取得命令の両方で構成されます。`measure()`は、プロセスを自動化するために提供されていますが、必要に応じて、`acquire()`および`play()`を使用して完全に制御することもできます。


### 便利な機能の紹介

1. パルスのスケジュールの可視化
`draw()`を利用して自分が定義したパルスフローを可視化することができます。

    ```python
    sample_sched.draw(backend=backend)
    ```
    ![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78339/535889cf-fddd-1301-ca4a-51c6fa08538e.png)

横軸は時間、縦軸はパルスを表していてD0は駆動パルス、M0は測定パルスを表現しています。（0は一つ目）まずは周波数が設定されその後、フロー通りGaussianパルスとmeasureパルスが実行されるスケジュールになっていることが分かります。ここで`draw()`にbackendを渡していますがこれはどのbackendを利用するか分からないので必要です。なにも指定しない場合`dt`という内部データを利用した値でパルスが表示されます。

1. パルス設定表示
`instructions`を使えば自分が定義したフローを上記とは違った見方で確認できます。自分が指定した内容が一覧で閲覧できるので便利です。

    ```python
    sample_sched.instructions
    ```

    ![instructions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78339/56236f3e-e110-a571-fd2d-1880addad760.png)

# まとめ
この記事ではBuilder構文について紹介しました。他にもいろいろ新しい機能が提供されているので紹介していきたいと思います。