Qiskit Metalとは、超伝導型の量子コンピューターデバイスの設計開発と解析ができるオープンソースのフレームワークです。ライブラリーを使って比較的簡単に量子デバイスをデザインすることができ、様々な電磁界シミュレーター(Ansys HFSSなど)と接続して、量子ビット周波数、非調和性など必要なパラメーターをシミュレーションし、その結果をもとにレイアウトを調整していくことができます。
インストール
(正式なインストールガイドはこちらです。)
Conda環境を用意し、
pip install qiski-metal
でインストールできますが、関連するライブラリーがインストールされていないとうまく動かないので、以下のように、Qiskit Metalのgithubリポジトリーからenvironment.ymlを使って新しいconda環境を作ってからインストールすると良さそうです。
git clone https://github.com/Qiskit/qiskit-metal.git
cd qiskit-metal
conda env create -n <環境の名前> environment.yml
conda activate <環境の名前>
python -m pip install --no-deps -e .
最後の「.(ピリオド)」を忘れずに。
全体の流れ
Qiskit Metalによる量子チップデザイン開発の基本のフローは、
- チップをデザイン(量子ビット、バス、Readout線、制御線など)
- 解析
- デザイン調整(解析と調整を繰り返す)
- デザイン決定
- GDS file (半導体レイアウトデータのファイル) に出力
- チップを製造
となりますが、「2. 解析」には、Ansysなどのシミュレーターが必要になるため、今回は「1. チップをデザイン」のみやってみます。Qiskit Metalがインストールされた環境で、Jupyter notebookから実行しました。
Metal GUIの起動
モジュールが変更されたときのためにモジュールの自動リロードを可能にし、必要なライブラリーをimportします。
# モジュールの自動リロードを有効にします
%load_ext autoreload
%autoreload 2
import qiskit_metal as metal
from qiskit_metal import designs, draw
from qiskit_metal import MetalGUI, Dict, open_docs
designs
の中から、平面図面の基本的な機能を提供するDesignPlanar()
を選択し、以下でMetal GUIを起動します。
design = designs.DesignPlanar()
gui = MetalGUI(design)
量子ビットのレイアウト
Metal GUIが表示できたら、GUI上のLibraryからTransmonPocket
を選んで「Create」を選ぶことで右側メインビューにトランズモン量子ビットを作成・レイアウトできます。
または、以下のようにJupyter notebookからコードでも作成することができます。
QLibrary
から、TransmonPocket
を選んで、Q1
という名前のトランズモン量子ビットを作成します。
from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket
q1 = TransmonPocket(design, 'Q1')
gui.rebuild() # デザインとプロットを再構築します
gui.edit_component('Q1') # GUI左下のOption表示をQ1のものに更新
gui.autoscale()
gui.screenshot() # jupyter notebook上にもGUIを表示します
この量子ビットQ1
の形状を変更するには、Metal GUI上でも左下のOptionsの値を手動で変更することで可能ですが、以下のようにJupyter notebook上のコードでも変更できます。
# オプションを変える
q1.options.pos_x = '0.5 mm'
q1.options.pos_y = '0.25 mm'
q1.options.pad_height = '225 um'
q1.options.pad_width = '250 um'
q1.options.pad_gap = '50 um'
# オプションを変えたので、ジオメトリをUpdateする
gui.rebuild()
gui.edit_component('Q1')
gui.autoscale()
量子ビットにピンをつける
量子ビットQ1に a、b、c、dという名前の4つのコネクターピンを追加します。一度すべてのqcomponentsを消去した後(または、既存のcomponentの上書きを可能にした後)、オプションでピンを設定して、そのオプション付きのqcomponentオブジェクトQ1
を作成します。
design.delete_all_components() # 一度全て消します。
# design.overwrite_enabled = True を上記の代わりに使っても良いです。
# オプションでピンを設定
options = dict(
connection_pads=dict(
a = dict(loc_W=+1,loc_H=+1), #右上
b = dict(loc_W=-1,loc_H=+1, pad_height='30um'), #左上
c = dict(loc_W=+1,loc_H=-1, pad_width='200um'), #右下
d = dict(loc_W=-1,loc_H=-1, pad_height='50um') #左下
)
)
# オプション付きで再び量子ビットのqcomponentオブジェクトを作成
q1 = TransmonPocket(design, 'Q1', options = dict(pos_x='+0.5mm', pos_y='+0.5mm', **options))
# デザインを再構築して表示
gui.rebuild()
gui.edit_component('Q1')
gui.autoscale()
これで、1つの量子ビットに4つのピンをつける方法が分かりました。次は、4量子ビットを配置して、配線し、量子チップ全体を作成します。
複数量子ビットをコネクタで接続する
まず、先ほどの方法でオプションを作り、そのオプションで4つのトランズモンQ1
、Q2
、Q3
、Q4
を作成します。
design.overwrite_enabled = True # 既存のコンポーネントの上書きを可能に
# 全てのトランズモンへのカスタムオプション
options = dict(
pad_width = '425 um',
pocket_height = '650um',
connection_pads=dict(
a = dict(loc_W=+1,loc_H=+1),
b = dict(loc_W=-1,loc_H=+1, pad_height='30um'),
c = dict(loc_W=+1,loc_H=-1, pad_width='200um'),
d = dict(loc_W=-1,loc_H=-1, pad_height='50um')
)
)
# 4つのトランズモンを作成
q1 = TransmonPocket(design, 'Q1', options = dict(
pos_x='+2.55mm', pos_y='+0.0mm', **options))
q2 = TransmonPocket(design, 'Q2', options = dict(
pos_x='+0.0mm', pos_y='-0.9mm', orientation = '90', **options))
q3 = TransmonPocket(design, 'Q3', options = dict(
pos_x='-2.55mm', pos_y='+0.0mm', **options))
q4 = TransmonPocket(design, 'Q4', options = dict(
pos_x='+0.0mm', pos_y='+0.9mm', orientation = '90', **options))
# デザインを再構築
gui.rebuild()
gui.autoscale()
次に、コプレナー導波路(coplanar waveguides (CPW))で4つのトランズモンをつなぎます。QLibrary
から基本的なCPW QComponentであるRouteMeander
というメアンダラインのクラスをインポートします。(メアンダ形状とは、導線を折り曲げてジグザグ状にした構造です。)オプションを以下のようにセットして、Q1
とQ2
をつないでみます。
from qiskit_metal.qlibrary.tlines.meandered import RouteMeander
options = Dict(
total_length= '6mm', # 配線長
pin_inputs=Dict(
start_pin=Dict(
component= 'Q1', # 量子ビット
pin= 'd'), # ピン
end_pin=Dict(
component= 'Q2',
pin= 'c')),
lead=Dict(
start_straight='0.1mm', # ピンからのクリアランス
end_straight='0.1mm'),
meander=Dict(
asymmetry='0mm'), # 位置
fillet = '90um' # 角を丸める
)
cpw1 = RouteMeander(design,'cpw1', options=options)
gui.rebuild()
gui.autoscale()
Q1
とQ2
がメアンダラインでつながりました。
関数を定義して、同じメアンダラインを繰り返し使って4つのトランズモン全てを接続します。
options = Dict(
meander=Dict(
lead_start='0.1mm',
lead_end='0.1mm',
asymmetry='0 um')
)
def connect(component_name: str, component1: str, pin1: str, component2: str, pin2: str,
length: str,
asymmetry='0 um', flip=False):
"""Connect two pins with a CPW."""
myoptions = Dict(
pin_inputs=Dict(
start_pin=Dict(
component=component1,
pin=pin1),
end_pin=Dict(
component=component2,
pin=pin2)),
lead=Dict(
start_straight='0.13mm'
),
total_length=length,
fillet = '90um')
myoptions.update(options)
myoptions.meander.asymmetry = asymmetry
myoptions.meander.lead_direction_inverted = 'true' if flip else 'false'
return RouteMeander(design, component_name, myoptions)
asym = 150
cpw1 = connect('cpw1', 'Q1', 'd', 'Q2', 'c', '6.0 mm', f'+{asym}um')
cpw2 = connect('cpw2', 'Q3', 'c', 'Q2', 'a', '6.1 mm', f'-{asym}um', flip=True)
cpw3 = connect('cpw3', 'Q3', 'a', 'Q4', 'b', '6.0 mm', f'+{asym}um')
cpw4 = connect('cpw4', 'Q1', 'b', 'Q4', 'd', '6.1 mm', f'-{asym}um', flip=True)
gui.rebuild()
gui.autoscale()
これで4つのトランズモン間の配線までが完了しました。
今回はここまでにします。
Metal GUIを閉じる
Metal GUIを閉じるには、直接、GUI上で「python」 -> 「Quit」などで画面を閉じるか、またはJupyter notebook上で以下のようにします。
gui.main_window.close()
参考文献: