4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

はじめに

量子コンピュータカレンダーも22日目となり、ディープな話が様々繰り広げられていますが、今日は軽めの内容とさせて頂きたいと思いますw(浅くてスミマセンw)
なお、量子コンピュータカレンダー参加も3年目となります!
過去(2020/2021)のカレンダにて投稿した記事については、本稿末尾にてリンクさせて頂くので、そちらもご笑覧いただければ幸いです。

やること

Quantinuumが提供するpytket(tket)ですが、プラットフォームに依存しないSDKを提供し、
合わせてターゲット量子マシンへのコンパイラ/トランスパイラの機能も提供しています。

このコンパイラ/トランスパイラの機能に興味を持ったのでちょっと試してみよう。

というのが本稿の趣旨です。

そういったコンパイル/トランスパイルならpytketを使わずともQiskitでも出来るじゃん。。

とかあるかもしれませんが、
純粋にpytketでどんな変換が出来るんだろう。を試してみるというスタンスなので、
あまり細かいことは気にせず進めてみたいと思います。

では、始めます

トランスパイラの機能は、pytket.passesパッケージで提供されているのですが、、
若干慣れが必要なので、まずは一番簡単な、Toffoliゲートの分解から始めたいと思います。

1)Toffoli(CCX)を分解

Toffoliゲート($CCX$ゲート)ですが、複数量子系の完全系である$H,T,T^{\dagger},CNOT$を用いてこんな等価回路に分解可能であると知られています。1

CCX.png

この等価回路をpytket.passesパッケージを用いて作成してみたいと思います。2

まずは、pipでモジュールを導入します。

!pip install pytket

次に、Toffoliを実装して、可視化します。

from pytket.circuit import Circuit
from pytket.circuit.display import render_circuit_jupyter

# 3量子ビットを準備
circ_toff = Circuit(3)

# Toffoli(CCX)ゲートをかける
circ_toff.CCX(0,1,2)

# 可視化
render_circuit_jupyter(circ_toff)

image.png

なお、量子回路の表示スタイルは、このボタンで変更できます。

image.png

では、回路を変換していきましょう。

from pytket.predicates import CompilationUnit
from pytket.passes import DecomposeMultiQubitsCX

# ①CompilationUnitで回路を包む
unit_toff = CompilationUnit(circ_toff)

# ②DecomposeMultiQubitsCXを使って回路を展開
DecomposeMultiQubitsCX().apply(unit_toff)

# ③展開後の回路を取り出し
transformed_cric = unit_toff.circuit

# 可視化
render_circuit_jupyter(transformed_cric)

image.png

といった具合に、無事に、Toffoliを分解することができました。
ポイントは、

  • ① 量子回路をpytketのSDKにて実装したら、その回路をCompilationUnitでラップし3
  • ② 所望の変換(上記ではDecomposeMultiQubitsCX)をapplyする
  • ③ apply後のCompilationUnitからcircuitを取り出すと変換後の回路が得られる

といったところでしょうか。

2)冗長な回路の除去

下記のような回路を考えます。

$X$ゲートの後に、$X$ゲートがかかっているので、ブロッホ球で考えるとX軸を中心に180度回転し、もう一度180度回転するので、360度回転となり、結局何もしていない回路となります。

もう一つ、複数量子系で考えて見ます。
下記はどうでしょうか?これも、SWAPしてSWAPしているので、結局元の状態に戻ります。
よって、下記も無駄のある冗長な回路と見なすことができます。

image.png

こういった無駄のある冗長な回路の排除を考えていきます。

では、始めます。
まずは、冗長な回路を作成してみましょう。

from pytket.circuit import Circuit
from pytket.circuit.display import render_circuit_jupyter

# 3量子ビットを準備
circ_redundant = Circuit(3)

# 冗長な回路を作成
circ_redundant.X(0).X(1).SWAP(0,1).SWAP(1,2).SWAP(2,1).SWAP(1,0).X(0).X(1).CX(0,2)

# 可視化
render_circuit_jupyter(circ_redundant)

image.png

この回路はいかがでしょうか?

  • SWAPはSWAPで無効化されるので、意味がない。
  • 0,1ビット目の$X$ゲートも、後方の$X$ゲートで元の状態に戻る為、意味がない。
  • 結局、意味のある処理は最後の$CX(0,2)$のCNOTだけ

ということで、前半の冗長な回路を除去していきます。

from pytket.predicates import CompilationUnit
from pytket.passes import CliffordSimp

# ① CompilationUnitで回路を包む
unit_redundant = CompilationUnit(circ_redundant)

# ② CliffordSimpを使って冗長な回路を除去
CliffordSimp().apply(unit_redundant)

# ③ 展開後の回路を取り出し
transformed_cric = unit_redundant.circuit

# ④ 可視化
render_circuit_jupyter(transformed_cric)

image.png

冗長な前半の回路が除去されて、CNOTだけが残りました。

CliffordSimp()ですが、リファレンスを読むと

An optimisation pass that performs a number of rewrite rules for simplifying Clifford gate sequences, similar to Duncan & Fagan (https://arxiv.org/abs/1901.10114). Given a circuit with CXs and any single-qubit gates, produces a circuit with TK1, CX gates.

といったように、簡略化のための書き換えルールを適用し、$CX$と任意の単一量子ゲートを持つ回路への変換により、冗長な回路が除去されました。
構造的には先程と一緒ですが、こんなイメージです。

image.png

3)後方の単一ゲートを前方に持ってくる

いきなりですが、こういった回路を考えます。

from pytket.circuit import Circuit
from pytket.circuit.display import render_circuit_jupyter

# 3量子ビットを準備
circ_com = Circuit(3)

# 後方に単一ゲートが多数
circ_com.CX(0,1).CX(0,2).X(1).X(2).X(1).X(2).X(1).X(2)

# 可視化
render_circuit_jupyter(circ_com)

image.png

この2つのCNOT($CX$)の背後にある、単一ゲートを前方に持ってくる様、書き換えをしてみたいと思います。この場合、単一ゲート($X$ゲート3つ)は、前方に交換可能(Commute可能)ですので、単純に$X$ゲートが前に出てくる変換となります。

from pytket.predicates import CompilationUnit
from pytket.passes import CommuteThroughMultis

# ① CompilationUnitで回路を包む
unit_com = CompilationUnit(circ_com)

# ② CommuteThroughMultisで、単一ゲートを前方へ
CommuteThroughMultis().apply(unit_com)

# ③ 展開後の回路を取り出し
transformed_cric = unit_com.circuit

# ④ 可視化
render_circuit_jupyter(transformed_cric)

image.png

処理の構造としては先程と一緒ですので、模式図は省略します。

4)単一ゲートを前方へ移動し、冗長な処理を排除

最後に、上記の前方へ移動した、$X$ゲート3つは冗長であり無用なゲートを排除します。

  • CommuteThroughMultis : 単一ゲートを前方へ
  • RemoveRedundancies  : 冗長ゲートを排除4
from pytket.predicates import CompilationUnit
from pytket.passes import SequencePass,RemoveRedundancies,CommuteThroughMultis
from pytket.passes import *

# ① CompilationUnitで回路を包む
unit_com = CompilationUnit(circ_com)

# ② 複数の処理を同時に適用
SequencePass(
    [
        CommuteThroughMultis(),  #CommuteThroughMultisで、単一ゲートを前方へ
        RemoveRedundancies()     #冗長性を排除
    ]
).apply(unit_com)

# ③ 展開後の回路を取り出し
transformed_cric = unit_com.circuit

# ④ 可視化
render_circuit_jupyter(transformed_cric)

image.png

単一ゲートが前方に交換し(Commuteし)、かつ、$XXX \rightarrow X$となり冗長性も排除できました。
この両方の処理を同時に実現するために、SequencePassを使っています。
image.png

まとめ

pytket.passesパッケージを使って、回路の書き換えを色々やってみました。
下記の公式サンプルでも良かったのですが、単純な回路のほうが説明がわかりやすいかと考え、回路自体に意味は無い単純な回路で、各機能の役割を見てみました。

pytket.passesパッケージは他にも、後述のとおり、様々(膨大)に機能があるので、皆さんも色々試して頂ければと思います。

おまけ①(過去のカレンダ投稿)

2020年

2021年

おまけ②(pytket.passesのパッケージ)

本当に、色々機能があるので、どれが何につかえるのか?は徐々に勉強していきたいと思います。
今回使った機能には、★をつけてあります。

  • pytket.passes.SequencePass() ★(4)
  • pytket.passes.AASRouting()
  • pytket.passes.CliffordSimp() ★(2)
  • pytket.passes.CnXPairwiseDecomposition()
  • pytket.passes.CommuteThroughMultis() ★(3,4)
  • pytket.passes.ComposePhasePolyBoxes()
  • pytket.passes.ContextSimp()
  • pytket.passes.CustomPass()
  • pytket.passes.CustomRoutingPass()
  • pytket.passes.CXMappingPass()
  • pytket.passes.DecomposeArbitrarilyControlledGates()
  • pytket.passes.DecomposeBoxes()
  • pytket.passes.DecomposeClassicalExp()
  • pytket.passes.DecomposeMultiQubitsCX() ★(1)
  • pytket.passes.DecomposeSingleQubitsTK1()
  • pytket.passes.DecomposeSwapsToCircuit()
  • pytket.passes.DecomposeSwapsToCXs()
  • pytket.passes.DecomposeTK2()
  • pytket.passes.DefaultMappingPass()
  • pytket.passes.DelayMeasures()
  • pytket.passes.EulerAngleReduction()
  • pytket.passes.FlattenRegisters()
  • pytket.passes.FullMappingPass()
  • pytket.passes.FullPeepholeOptimise()
  • pytket.passes.GlobalisePhasedX()
  • pytket.passes.GuidedPauliSimp()
  • pytket.passes.KAKDecomposition()
  • pytket.passes.NaivePlacementPass()
  • pytket.passes.NormaliseTK2()
  • pytket.passes.OptimisePhaseGadgets()
  • pytket.passes.PauliSimp()
  • pytket.passes.PauliSquash()
  • pytket.passes.PeepholeOptimise2Q()
  • pytket.passes.PlacementPass()
  • pytket.passes.RebaseCustom()
  • pytket.passes.RebaseTket()
  • pytket.passes.RemoveBarriers()
  • pytket.passes.RemoveDiscarded()
  • pytket.passes.RemoveRedundancies() ★(4)
  • pytket.passes.RenameQubitsPass()
  • pytket.passes.RoutingPass()
  • pytket.passes.SimplifyInitial()
  • pytket.passes.SimplifyMeasured()
  • pytket.passes.SquashCustom()
  • pytket.passes.SquashRzPhasedX()
  • pytket.passes.SquashTK1()
  • pytket.passes.SynthesiseHQS()
  • pytket.passes.SynthesiseOQC()
  • pytket.passes.SynthesiseTK()
  • pytket.passes.SynthesiseTket()
  • pytket.passes.SynthesiseUMD()
  • pytket.passes.ThreeQubitSquash()
  • pytket.passes.ZZPhaseToRz()
  1. https://en.wikipedia.org/wiki/Toffoli_gate

  2. なお、これくらいのトランスパイルであれば、Qiskitでも実装されています。
    詳細は、Qiskitチュートリアル:トランスパイラー パスとパス マネージャー をご確認ください。

  3. Compilationのサンプルでは、In order to apply a pass to a circuit, we must first create a CompilationUnit from it. We can think of this as a 'bridge' between the circuit and the pass. The CompilationUnit is constructed from the circuit; the pass is applied to the CompilationUnit; and the transformed circuit is extracted from the CompilationUnit: との記載があったので、このクラスでラップするのがお作法の様に見えたため、こういった処理にしています。
    一方で、CompilationUnitでラップせずとも量子回路をそのままpassesにapplyできる様です。

  4. 冗長性の排除にCliffordSimpを使っても良かったのですが、この処理だと単一ゲート操作が、TK1ゲートという独自ゲートに変換されてしまい見づらかったので、RemoveRedundanciesを使うことにしました。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?