さて、Qiskitにはtranspile()
関数があります(ドキュメントを参照してください)。トランスパイラに関する私の理解は、異なるバックエンドでアルゴリズムを実行する目的で、あるゲート操作のセットを別のゲート操作のセットに変換する方法として最もよく説明されています (キュービットの接続性、つまりアーキテクチャのジオメトリが異なるため)。ある量子コンピューターから別の量子コンピューターへ)。冗長性を減らし、アダマール ゲートによって結合された CNOT を CZ に変更してゲート数を減らすなど、同等のゲートに関して物事を書き直すことによって、回路を最適化する方法があります。ハードウェア バックエンドにネイティブ CZ がない場合は、正反対のことを行い、CZ からアダマールによって結合された CNOT に移動することもできます。一般に、固定ハードウェア バックエンドの任意の回路を最適化するためのこの種のトランスパイルは、QMA 完全な問題です (こちらを参照)。たとえば...誰かが似たようなことにLEANを使ったことがあるのではないでしょうか?)。最適な回路を近似するために変分法が使用されることもありますが、ここでは脱線します。
わずかに異なるが関連する問題: Nielsen & Chuangの付録 3 の Kitaev-Solovay Theorem と4.5 の資料を使用すると、任意のユニタリ ゲートをユニバーサル ゲート セットで常に「効率的に」近似できることがわかります (これは、ここでは必ずしも重要ではありません)。どれほど効率的かは未解決の問題だと思いますが、少なくとも上限と下限があります。
これを考えると、回路を最適化するために Qiskittranspile()
関数がユニタリ ゲートを近似し、ゲート セットを最適な (最小化された) ゲート セットにリファクタリングすることが期待されますが、多くの非標準ゲートを含む大規模な回路で問題が発生する可能性があります。ただし、単純な例でも機能させるのに問題があります。たとえば、3 つのキュービットの順列行列は、近似するのに妥当なユニタリのように見えます (一部は、手動で SWAP ゲートと X ゲートに簡単に変換できます)。しかし、Qiskit はこれを行うのが好きではないようで、その理由を理解する助けが必要です。例として、Qiskit でユニタリ (順列) 演算子を定義し、次のように量子回路のゲートに変換できます。
from qiskit import *
from qiskit.quantum_info import Operator
from qiskit.compiler import transpile
%matplotlib inline
permute = Operator([[0, 0, 1, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 1, 0, 0, 0]])
qc = QuantumCircuit(3)
qc.unitary(permute, [0,1,2], label='P')
qc.draw(output='mpl')
さて、transpile()
次のようにQiskitで関数を使用しようとすると:
result = transpile(qc, basis_gates=['u1', 'u2', 'u3', 'cx'], optimization_level=3)
result.draw(output='mpl')
で終わる巨大で長い恐ろしいエラーが発生します。
NotImplementedError: Not able to generate a subcircuit for a 3-qubit unitary
それで、私の質問は...なぜだと思いますか。笑。いいえ、真剣に、これを間違った方法で使用しているだけですか? 私の期待は高すぎますか?私がやりたいことをするための合理的な方法はありますか?ベーシス ゲートの別のセットは機能しますか? もしそうなら、ベーシスゲートをどのように決定しますか?また、それぞれのソースコードを見ると、関数の機能がより制限されているように見えるdecompose()
関数(ドキュメントを参照)も試しました。transpile()
関数decompose()
が実装されます (このビデオとこのビデオで確認できます)。transpile()
関数も実装されています (このビデオの約 10:35 セル In[18] と彼の議論を参照してください)。彼を使用してコマンドを実行することもできます
from qiskit import transpile
また、そのインポートでも機能しません。transpile()
関数(またはその関数)が期待どおりに機能しない理由を誰かが理解している場合decompose()
は、説明が大好きです。ありがとう!!!
- - - - -アップデート - - - - -
私はさらに別の問題を発見しました。使用する場合
from qiskit.circuit.random import random_circuit
rcirc2 = random_circuit(3, 4)
rcirc2.draw(output='mpl')
ランダムな回路を生成してから実行します
from qiskit.compiler import transpile
result2 = transpile(rcirc2, basis_gates=['u1', 'u2', 'u3', 'cx'], optimization_level=3)
result2.draw(output='mpl')
一部の結果 (3 キュービット ゲートなし) はトランスパイルされず、一部の結果はトランスパイルされます。したがって、これは、transpile()
. 注: 回路は「ランダム」であるため、3 キュービット ゲートのない回路を取得するには、このコードを数回試行する必要がある場合があります。たとえば、次の回路はトランスパイルしません。
circ = QuantumCircuit(3)
circ.i(0)
circ.ch(2,1)
circ.cx(0,1)
circ.t(2)
circ.cx(2,0)
circ.x(0)
circ.u1(3.41, 1)
circ.ch(2,1)
circ.draw(output='mpl')
私たちが走るとき
result3 = transpile(circ, basis_gates=['u1', 'u2', 'u3', 'cx'], optimization_level=3)
result3.draw(output='mpl')
バリアを追加してすべての独立したゲートを個別のステップに分離することも、役に立たないようです。したがって、並列実行の問題ではなく、独立したゲート操作です。
----------アップデート2----------
Qiskit を使用してランダムな 3 キュービット ユニタリを生成すると、これらも機能しません。
from qiskit.quantum_info import Operator, random_unitary
U = random_unitary(8, seed=None)
qc = QuantumCircuit(4, 4)
qc.unitary(U, [0,1,3], label='P')
qc.draw(output='mpl')
ユニタリが動作するキュービットを再定義するか、回路を 3 キュービット回路に縮小するか、この方法でより大きな n キュービット ユニタリを生成することができます。これらの例はどれも機能しません。