Aplicando uma porta quântica de múltiplos qubit a qubits específicos

9

Uma matriz não gate controlada é assim:

[10 00 00 00 010 00 00 00 00 010 00 010 0]

Isso funciona muito bem quando você tem apenas dois qubits e deseja usar o primeiro qubit como controle e o segundo qubit como entrada a ser invertida (ou não).

Existe um método para converter essa matriz para usar, por exemplo, se você tivesse 3 qubits e desejasse usar o qubit 1 como controle e o qubit 3 como a entrada que é possivelmente invertida?

Pensando nisso logicamente, eu posso pensar nisso:

[1000000001000000001000000001000000000100000010000000000100000010]

Existe uma maneira melhor, mais formal / generalizada de converter portas multi-bits para usar quaisquer qubits especificados, em vez do primeiro N em um N circuito qubit?

Alan Wolfe
fonte

Respostas:

7

Expand-n-Swap

Se você deseja aplicar um portão a um subconjunto dos qubits:

Pode ser entediante fazer todas essas grandes multiplicações de matrizes, mas as matrizes de troca são esparsas e a ideia é muito direta.

Os controles são mais fáceis

No caso de adicionar controles a uma operação (que se aplica ao exemplo específico que você deu), há um truque mais fácil. Apenas expanda a operação como normal, mas substitua qualquer parte da matriz que corresponda às entradas com falha de controle pelo que seria a matriz de identidade.

É um pouco mais fácil acompanhar se você introduzir um "valor de controle" falsocque substitui o comportamento usual do produto tensor , de modo que, em vez de[c]você=cvocê, Você tem [c]você=cEu (em outras palavras: quando uma entrada é c você não telha você sobre a entrada e a escala vocêpela entrada; você usaEu ao invés de você)

Defina a "operação" de um controle qubit-must-be-ON para ser C=[c0 00 01]. Um no-op éEue NÃO é X. Em seguida, a operação da sua pergunta pode ser calculada assim (assumindo a ordem big endian):

CNOT31=CEuX

=[c0 00 01][10 00 01][0 0110 0]

=[c[10 00 01]0 0[10 00 01]0 0[10 00 01]1[10 00 01]][0 0110 0]

=[[c0 00 0c][0 00 00 00 0][0 00 00 00 0][10 00 01]][0 0110 0]

=[c0 00 00 00 0c0 00 00 00 010 00 00 00 01][0 0110 0]

(observação: usar um único zero para significar ambiguamente uma matriz zero de 2x2, quando conveniente)

=[c[0 0110 0]0 00 00 00 0c[0 0110 0]0 00 00 00 0[0 0110 0]0 00 00 00 0[0 0110 0]]

=[[c0 00 0c]0 00 00 00 0[c0 00 0c]0 00 00 00 0[0 0110 0]0 00 00 00 0[0 0110 0]]

=[c0 00 00 00 00 00 00 00 0c0 00 00 00 00 00 00 00 0c0 00 00 00 00 00 00 00 0c0 00 00 00 00 00 00 00 00 010 00 00 00 00 00 010 00 00 00 00 00 00 00 00 00 010 00 00 00 00 00 010 0]

(agora concluímos os produtos tensores e não precisamos do cé mais)

[10 00 00 00 00 00 00 00 010 00 00 00 00 00 00 00 010 00 00 00 00 00 00 00 010 00 00 00 00 00 00 00 00 010 00 00 00 00 00 010 00 00 00 00 00 00 00 00 00 010 00 00 00 00 00 010 0]

Faz sentido?

Craig Gidney
fonte
8

Não use o método de troca, é muito ineficiente. E a resposta da outra pessoa é específica para o portal CNOT e, para ser franco, complica demais as coisas.

Aqui está um algoritmo muito simples que resolve seu problema em todos os casos, não apenas no portal CNOT, para quaisquer bits arbitrários.

O algoritmo:

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

Nos computadores clássicos, existe algo conhecido como "decodificador". Digamos que eu tenho apenas 3 fios, efetivamente, 3 bits. Mas eu quero controlar 8 fios. Isso pode ser feito? Sim, porque 3 bits tem 8 possibilidades diferentes: 000, 001, 010, 011, 100, 101, 110, 111. Portanto, podemos atribuir cada possibilidade a um dos nossos 8 fios de saída. Isso é chamado de "decodificação".

Se eu passar o número 101 e tivermos 3 bits, sabemos 101 = 5, então configurarei o fio de saída 5 para uma alta tensão e os outros 7 fios de saída serão 0, que podemos representar assim: decode (101) = [0, 0, 0, 0, 0, 1, 0, 0].

Neste algoritmo, menciono a "função de transformação" chamada "f". Para computadores clássicos, a função de transformação está apenas recebendo um valor de entrada e retornando a versão "decodificada" do valor de saída. Portanto, se tivermos 3 bits e a saída for 4, retornaremos [0, 0, 0, 0, 1, 0, 0, 0]. Em seguida, atribuímos isso como a coluna da nossa matriz a esse valor.

Vamos pensar em "decodificação" em termos de qubits. Como podemos decodificar os qubits | 101>?

Sabemos que para nossos vetores de probabilidade de qubit, | 0> é [1, 0] e | 1> é [0, 1]. A decodificação de qubits pode ser feita como o produto Kronecker.

Portanto, se convertermos cada bit no equivalente de vetor de probabilidade e pegarmos o produto Kronecker de todos eles, obteremos ...

|101> = |1> ⊗ |0> ⊗ |1> = [0, 1] ⊗ [1, 0] ⊗ [0, 1] = [0, 0, 0, 0, 0, 1, 0, 0]

É assim que queremos decodificar qubits. Este algoritmo pode ser aplicado a qubits da mesma forma usando isso.

Vamos tentar este algoritmo em um problema mais simples.

Vamos supor que temos um sistema com apenas 2 qubits. Se queremos aplicar o portão Hadamard a apenas 1 qubit, podemos gerar um portão lógico para ambos os qubits que aplique apenas o portão Hadamard a um único qubit. Vamos supor que o qubit único ao qual queremos aplicá-lo seja o qubit mais significativo e o menos significativo não será afetado.

Queremos uma função de transformação que, para cada uma de nossas entradas possíveis, produza a saída correta. Temos dois qubits, isso significa que existem quatro saídas possíveis.

f(|00>) = ?
f(|01>) = ?
f(|10>) = ?
f(|11>) = ?

Sabemos que o qubit menos significativo não será afetado, para que possamos preenchê-lo.

f(|00>) = ? ⊗ |0>
f(|01>) = ? ⊗ |1>
f(|10>) = ? ⊗ |0>
f(|11>) = ? ⊗ |1>

Também sabemos o que o Hadamard faz com um qubit, de modo que:

H(|0>) = 1/sqrt(2)|0> + 1/sqrt(2)|1>
H(|1>) = 1/sqrt(2)|0> - 1/sqrt(2)|1>

Portanto, nossa função de transformação é simplesmente:

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>

Expanda isso para nosso formulário de vetor de probabilidade normalizado ...

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 ]

Agora vamos resolver isso ...

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) ]

Essa é a nossa função de transformação.

Nossa matriz de portas lógicas, "lgm", é do tamanho 2 ^ n por 2 ^ n onde n = número de qubits sendo simulados; portanto, neste caso, é 2 ^ 2 por 2 ^ 2 ou 4x4. Nosso algoritmo nos diz que, para cada coluna i, defina a coluna igual a f (i). Definimos nossa função de transformação de probabilidade, para que possamos preencher facilmente essas colunas.

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) ]

Agora, o passo final em nosso algoritmo é simplesmente multiplicar nossa matriz, representando todo o sistema quântico, sys, por esse portão lógico, lgm.

E isso faz o que queremos. Ele aplicará o portão hadamard apenas ao qubit mais alto e deixará o qubit menos significativo em paz. Se você não acredita em mim, pode tentar e ver se funciona.

A razão disso ser tão poderoso é porque se aplica a qualquer caso.

Vamos tentar este algoritmo no seu problema.

Imagine que temos um sistema de 3 qubit e queremos aplicar uma porta CNOT para qubit [0] e qubit [2]. Se você procurar a matriz CNOT na Wikipedia, essa matriz se aplica apenas a um sistema de 2 qubit. Uma solução ingênua seria anexar matrizes de identidade a ela usando o produto Kronecker para fazê-lo funcionar em sistemas com três qubits. Mas isso falha aqui: qubit [0] e qubit [2] não são adjacentes; portanto, simplesmente anexar matrizes de identidade não funcionará.

Nós poderia trocar qubit [0] com o qubit [1], aplicar o portão CNOT, então trocá-los de volta. Mas isso é lento. Em vez disso, poderíamos simplesmente gerar uma porta CNOT não adjacente para o nosso problema usando o algoritmo acima.

Primeiro, precisamos criar uma função de transformação para cada caso.

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>

Se você entende o portal CNOT, pode entender por que essa é a nossa função. Pense nisso como uma tabela da verdade. Como nosso qubit de controle é o qubit mais significativo, qubit [2], somente quando esse qubit for | 1> o qubit menos significativo, qubit [0], será negado.

Expanda isso para nosso formulário de vetor de probabilidade normalizado ...

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 ]

Agora vamos resolver isso ...

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 ]

Vamos fazer dessas as colunas da nossa matriz 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 ]

Agora, se a matriz multiplicar toda a matriz do sistema, sys, pela matriz da porta lógica, lgm, nosso resultado será o efeito de aplicar a porta CNOT ao qubit [2] e qubit [0] onde qubit [2] é o controle qubit.

Amelia Hartman
fonte
Obrigado por incluir um exemplo no final; foi muito útil Você também poderia fornecer uma definição do produto Kronecker? (Eu também acho que você pode ter digitado incorretamente como "Kornecker" uma vez.)
Pro Q
1
Eu recomendo isso para o produto Kronecker: youtube.com/watch?v=e1UJXvu8VZk
Amelia Hartman