swapメソッドは使用しないでください。非常に非効率的です。そして、他の人の答えはCNOTゲートに固有であり、率直に言って、物事を非常に複雑にします。
これは、任意のビットのCNOTゲートだけでなく、すべてのケースで問題を解決する非常に単純なアルゴリズムです。
アルゴリズム:
let sys = matrix representing the current state of the system
let n = number of qubits being simulated
let lgm = logic gate matrix of size 2^n by 2^n
let f = our logic gate transformation function
for i = 0 to (2^n) - 1:
lgm[column = i] = f(i)
sys = sys × lgg
古典的なコンピュータには、「デコーダ」と呼ばれるものがあります。たった3本のワイヤーしかなく、事実上3ビットであるとしましょう。しかし、8本のワイヤーを制御したいと思います。それはできますか?はい、3ビットには000、001、010、011、100、101、110、111の8つの異なる可能性があるため、8つの出力ワイヤーの1つに各可能性を割り当てることができます。これを「デコード」と呼びます。
101を渡し、3ビットがある場合、101 = 5であることがわかっているため、出力ワイヤ5を高電圧に設定し、他の7つの出力ワイヤは0になり、次のように表すことができます。 (101)= [0、0、0、0、0、1、0、0]。
このアルゴリズムでは、「f」と呼ばれる「変換関数」について言及します。従来のコンピューターの場合、変換関数は入力値を取り込んで、出力値の「デコードされた」バージョンを返すだけです。したがって、3ビットで出力が4の場合、[0、0、0、0、1、0、0、0]を返します。次に、それをその値の行列の列として割り当てます。
キュービットの観点から「デコード」を考えてみましょう。キュービット| 101>をどのようにデコードできますか?
キュービット確率ベクトルでは、| 0>は[1、0]、| 1>は[0、1]です。キュービットのデコードは、いわゆるクロネッカー製品で実行できます。
したがって、各ビットを同等の確率ベクトルに変換し、それらすべてのクロネッカー積を取ると、...
|101> = |1> ⊗ |0> ⊗ |1> = [0, 1] ⊗ [1, 0] ⊗ [0, 1] = [0, 0, 0, 0, 0, 1, 0, 0]
これは、キュービットをデコードする方法です。このアルゴリズムは、これを使用してまったく同じキュービットに適用できます。
より単純な問題でこのアルゴリズムを試してみましょう。
量子ビットが2つしかないシステムがあるとします。アダマールゲートを1キュビットにのみ適用する場合は、アダマールゲートを1つのキュビットにのみ適用する両方のキュビットの論理ゲートを生成できます。適用したい単一のキュービットが最も重要なキュービットであり、最も重要でないキュービットは影響を受けないと仮定しましょう。
可能な入力ごとに正しい出力を生成する変換関数が必要です。2つの量子ビットがあります。つまり、4つの出力が可能です。
f(|00>) = ?
f(|01>) = ?
f(|10>) = ?
f(|11>) = ?
最下位キュービットは影響を受けないことがわかっているので、それを埋めることができます。
f(|00>) = ? ⊗ |0>
f(|01>) = ? ⊗ |1>
f(|10>) = ? ⊗ |0>
f(|11>) = ? ⊗ |1>
我々はまた、アダマールがキュービットに対して何をするかを知っています。
H(|0>) = 1/sqrt(2)|0> + 1/sqrt(2)|1>
H(|1>) = 1/sqrt(2)|0> - 1/sqrt(2)|1>
したがって、変換関数は単純です。
f(|00>) = (1/sqrt(2)|0> + 1/sqrt(2)|1>) ⊗ |0>
f(|01>) = (1/sqrt(2)|0> + 1/sqrt(2)|1>) ⊗ |1>
f(|10>) = (1/sqrt(2)|0> - 1/sqrt(2)|1>) ⊗ |0>
f(|11>) = (1/sqrt(2)|0> - 1/sqrt(2)|1>) ⊗ |1>
これを正規化された確率ベクトル形式に展開します...
f(|00>) = [ 1/sqrt(2), 1/sqrt(2) ] ⊗ [ 1, 0 ]
f(|01>) = [ 1/sqrt(2), 1/sqrt(2) ] ⊗ [ 0, 1 ]
f(|10>) = [ 1/sqrt(2), -1/sqrt(2) ] ⊗ [ 1, 0 ]
f(|11>) = [ 1/sqrt(2), -1/sqrt(2) ] ⊗ [ 0, 1 ]
これを実際に解決しましょう...
f(|00>) = [ 1/sqrt(2), 0, 1/sqrt(2), 0 ]
f(|01>) = [ 0, 1/sqrt(2), 0, 1/sqrt(2) ]
f(|10>) = [ 1/sqrt(2), 0, -1/sqrt(2), 0 ]
f(|11>) = [ 0, 1/sqrt(2), 0, -1/sqrt(2) ]
それが変換関数です。
ロジックゲートマトリックス "lgm"のサイズは2 ^ n x 2 ^ nで、n =シミュレーションされるキュビットの数なので、この場合は2 ^ 2 x 2 ^ 2または4x4です。私たちのアルゴリズムは、各列iについて、列をf(i)に設定することを教えてくれます。確率変換関数を定義したので、これらの列に簡単に入力できます。
lgm =
|00> |01> |10> |11>
[ 1/sqrt(2), 0, 1/sqrt(2), 0 ]
[ 0, 1/sqrt(2), 0, 1/sqrt(2) ]
[ 1/sqrt(2), 0, -1/sqrt(2), 0 ]
[ 0, 1/sqrt(2), 0, -1/sqrt(2) ]
アルゴリズムの最後のステップは、量子システム全体を表す行列sysをこの論理ゲートlgmで単純に行列乗算することです。
そして、それは私たちが望むことを行います。ハダマードゲートは最上位のキュービットにのみ適用され、最下位のキュービットはそのままになります。私を信じていない場合は、自分で試してみて、動作することを確認してください。
これが非常に強力である理由は、どのような場合にも当てはまるためです。
このアルゴリズムを問題に試してみましょう。
3量子ビットシステムがあり、qubit [0]とqubit [2]にCNOTゲートを適用したいとします。ウィキペディアでCNOTマトリックスを検索すると、そのマトリックスは2キュービットシステムにのみ適用されます。素朴な解決策は、Kronecker製品を使用して単位行列を追加し、3つのキュービットを持つシステムで機能させることです。しかし、これはここでは失敗します。qubit[0]とqubit [2]は隣接していないため、単純に単位行列を追加しても機能しません。
我々は可能性が戻ってそれらを交換、その後、量子ビットを[1] [0]を量子ビットを入れ替えるCNOTゲートを適用します。しかし、それは遅いです。代わりに、上記のアルゴリズムを使用して、問題の隣接しないCNOTゲートを生成するだけで済みます。
最初に、各ケースの変換関数を考え出す必要があります。
f(|000>) = |0> ⊗ |0> ⊗ |0>
f(|001>) = |0> ⊗ |0> ⊗ |1>
f(|010>) = |0> ⊗ |1> ⊗ |0>
f(|011>) = |0> ⊗ |1> ⊗ |1>
f(|100>) = |1> ⊗ |0> ⊗ |1>
f(|101>) = |1> ⊗ |0> ⊗ |0>
f(|110>) = |1> ⊗ |1> ⊗ |1>
f(|111>) = |1> ⊗ |1> ⊗ |0>
CNOTゲートを理解すれば、これが私たちの機能である理由を理解できます。これを真理値表のように考えてください。制御量子ビットは最上位の量子ビットqubit [2]であるため、その量子ビットが| 1>の場合にのみ、最下位の量子ビットqubit [0]が無効になります。
これを正規化された確率ベクトル形式に展開します...
f(|000>) = [ 1, 0 ] ⊗ [ 1, 0 ] ⊗ [ 1, 0 ]
f(|001>) = [ 1, 0 ] ⊗ [ 1, 0 ] ⊗ [ 0, 1 ]
f(|010>) = [ 1, 0 ] ⊗ [ 0, 1 ] ⊗ [ 1, 0 ]
f(|011>) = [ 1, 0 ] ⊗ [ 0, 1 ] ⊗ [ 0, 1 ]
f(|100>) = [ 0, 1 ] ⊗ [ 1, 0 ] ⊗ [ 0, 1 ]
f(|101>) = [ 0, 1 ] ⊗ [ 1, 0 ] ⊗ [ 1, 0 ]
f(|110>) = [ 0, 1 ] ⊗ [ 0, 1 ] ⊗ [ 0, 1 ]
f(|111>) = [ 0, 1 ] ⊗ [ 0, 1 ] ⊗ [ 1, 0 ]
これを実際に解決しましょう...
f(|000>) = [ 1, 0, 0, 0, 0, 0, 0, 0 ]
f(|001>) = [ 0, 1, 0, 0, 0, 0, 0, 0 ]
f(|010>) = [ 0, 0, 1, 0, 0, 0, 0, 0 ]
f(|011>) = [ 0, 0, 0, 1, 0, 0, 0, 0 ]
f(|100>) = [ 0, 0, 0, 0, 0, 1, 0, 0 ]
f(|101>) = [ 0, 0, 0, 0, 1, 0, 0, 0 ]
f(|110>) = [ 0, 0, 0, 0, 0, 0, 0, 1 ]
f(|111>) = [ 0, 0, 0, 0, 0, 0, 1, 0 ]
これらをlgm行列の列にしましょう。
lgm =
[ 1, 0, 0, 0, 0, 0, 0, 0 ]
[ 0, 1, 0, 0, 0, 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, 1, 0, 0, 0 ]
[ 0, 0, 0, 0, 0, 0, 0, 1 ]
[ 0, 0, 0, 0, 0, 0, 1, 0 ]
ここで、システム全体の行列sysを論理ゲート行列lgmで行列乗算すると、結果はCNOTゲートをqubit [2]とqubit [0]に適用した効果になります。qubit[2]はコントロールです。キュービット。