Skip to main content
IBM Quantum Platform

Ansaetze e formas variacionais

No centro de todos os algoritmos variacionais está a ideia principal de analisar as diferenças entre os estados, que são convenientemente relacionados por meio de algum mapeamento bem comportado (por exemplo, contínuo, diferenciável) de um conjunto de parâmetros ou variáveis - daí o nome.

Primeiro, exploraremos como construir circuitos parametrizados manualmente. Usaremos esses circuitos para definir um Camadas de portas parametrizadas que são repetidas um determinado número de vezes, e os parâmetros das portas são otimizados durante o algoritmo para minimizar a função de custo. que representa uma coleção de estados parametrizados para o nosso algoritmo variacional explorar. Em seguida, construiremos nosso site Combinação de um operador de referência e uma forma variacional, para descrever o espaço de pesquisa que estamos explorando. aplicando essa forma variacional ao nosso estado de referência.

Também exploraremos como negociar velocidade versus precisão ao explorar esse espaço de pesquisa.

Um diagrama que mostra os principais componentes da discussão de ansatz, incluindo ansaetze heurística e ansaetze específica do problema.

Circuitos quânticos parametrizados

Os algoritmos variacionais operam explorando e comparando uma gama de estados quânticos ψ(θ)|\psi(\vec{\theta})\rangle, que dependem de um conjunto finito de parâmetros kk θ=(θ0,,θk1)\vec{\theta} = (\theta^0, \ldots, \theta^{k-1}). Esses estados podem ser preparados usando um circuito quântico parametrizado, em que as portas são definidas com parâmetros ajustáveis. É possível criar esse circuito parametrizado sem vincular ângulos específicos ainda:

from qiskit.circuit import QuantumCircuit, Parameter

theta = Parameter("θ")

qc = QuantumCircuit(3)
qc.rx(theta, 0)
qc.cx(0, 1)
qc.x(2)

qc.draw("mpl")

Output:

Output of the previous code cell
from math import pi

angle_list = [pi / 3, pi / 2]
circuits = [qc.assign_parameters({theta: angle}) for angle in angle_list]

for circuit in circuits:
    display(circuit.draw("mpl"))

Output:

Output of the previous code cell Output of the previous code cell

Forma variacional e Ansatz

Para otimizar iterativamente a partir de um estado de referência ρ|\rho\rangle para um estado-alvo ψ(θ)|\psi(\vec\theta)\rangle, precisamos definir uma forma variacional UV(θ)U_V(\vec{\theta}) que represente um conjunto de estados parametrizados para o nosso algoritmo variacional explorar:

0URUR0=ρUV(θ)UA(θ)0=UV(θ)UR0=UV(θ)ρ=ψ(θ)\begin{aligned} |0\rangle \xrightarrow{U_R} U_R|0\rangle & = |\rho\rangle \xrightarrow{U_V(\vec{\theta})} U_A(\vec{\theta})|0\rangle \\[1mm] & = U_V(\vec{\theta})U_R|0\rangle \\[1mm] & = U_V(\vec{\theta})|\rho\rangle \\[1mm] & = |\psi(\vec{\theta})\rangle \\[1mm] \end{aligned}

Observe que o estado parametrizado depende tanto do estado de referência ρ|\rho\rangle, que não depende de nenhum parâmetro, quanto da forma variacional UV(θ)U_V(\vec{\theta}), que sempre depende de parâmetros. Referimo-nos à combinação dessas duas metades como um ansatz: UA(θ):=UV(θ)URU_A(\vec\theta) := U_V(\vec\theta)U_R.

À medida que construímos nosso ansatz para representar uma coleção de estados parametrizados para o nosso algoritmo variacional explorar, percebemos uma questão importante: a dimensionalidade. Um sistema de nn -qubit (ou seja, espaço de Hilbert) tem um grande número de estados quânticos distintos no espaço de configuração. Seria necessário um número excessivo de parâmetros para explorá-lo completamente. Quantitativamente, sua dimensionalidade é D=22nD = 2^{2n}. Para piorar a situação, a complexidade do tempo de execução dos algoritmos de busca, e de outros semelhantes, cresce exponencialmente com essa dimensionalidade, um fenômeno muitas vezes mencionado na literatura como a maldição da dimensionalidade.

Para evitar esse contratempo, é prática comum impor algumas restrições razoáveis à forma variacional, de modo que apenas os estados mais relevantes sejam explorados. Encontrar um ansatz truncado eficiente é uma área de pesquisa ativa, mas abordaremos dois projetos comuns.


Abordagens heurísticas e compromissos

Se não tiver nenhuma informação sobre seu problema específico que possa ajudar a restringir a dimensionalidade, você pode tentar uma família arbitrária de circuitos parametrizados com menos de 22n2^{2n} parâmetros. No entanto, há algumas compensações a serem consideradas:

  • Velocidade : ao reduzir o espaço de pesquisa, o algoritmo pode ser executado mais rapidamente.
  • Precisão : Reduzir o espaço pode levar ao risco de excluir a solução real do problema, resultando em soluções abaixo do ideal.
  • Ruído : Circuitos mais profundos são afetados pelo ruído, portanto, precisamos fazer experiências com a conectividade, as portas e a fidelidade das portas do nosso ansatz.

Há um compromisso fundamental entre qualidade (ou mesmo capacidade de resolução) e velocidade: quanto mais parâmetros, maior a probabilidade de encontrar um resultado preciso, mas mais tempo levará para executar o algoritmo.

Circuitos locais N

Um dos exemplos mais usados de respostas heurísticas são os circuitos N-locais, por alguns motivos:

  • Implementação eficiente : O ansatz N-local é normalmente composto de portas locais simples que podem ser implementadas com eficiência em um computador quântico, usando um pequeno número de qubits físicos. Isso facilita a construção e a otimização de circuitos quânticos.
  • Captura correlações importantes : O ansatz N-local pode capturar correlações importantes entre os qubits em um sistema quântico, mesmo com um pequeno número de portas. Isso ocorre porque as portas locais podem atuar em qubits vizinhos e criar emaranhamento entre eles, o que pode ser importante para a simulação de sistemas quânticos complexos.

Esses circuitos consistem em camadas de rotação e emaranhamento que são repetidas alternativamente uma ou mais vezes da seguinte forma:

  • Cada camada é formada por portas de tamanho máximo NN, em que NN deve ser menor que o número de qubits.
  • Em uma camada de rotação, as portas são empilhadas umas sobre as outras. Podemos usar operações de rotação padrão, como RX ou CRZ.
  • Para uma camada de emaranhamento, podemos usar portas como Toffoli g ates ou CX com uma estratégia de emaranhamento.
  • Os dois tipos de camadas podem ser parametrizados ou não, mas pelo menos um deles precisa conter parâmetros. Caso contrário, sem pelo menos um parâmetro, não haveria variações!
  • Opcionalmente, uma camada de rotação extra é adicionada à extremidade do circuito.

Por exemplo, vamos criar um circuito de cinco qubits NLocal com blocos de rotação formados por RX e CRZ blocos de emaranhamento formados por portas Toffoli que atuam nos qubits [0,1,2][0,1,2], [0,2,3][0,2,3], [4,2,1][4,2,1] e [3,1,0][3,1,0] e 22 repetições de cada camada.

from qiskit.circuit.library import NLocal, CCXGate, CRZGate, RXGate
from qiskit.circuit import Parameter

theta = Parameter("θ")
ansatz = NLocal(
    num_qubits=5,
    rotation_blocks=[RXGate(theta), CRZGate(theta)],
    entanglement_blocks=CCXGate(),
    entanglement=[[0, 1, 2], [0, 2, 3], [4, 2, 1], [3, 1, 0]],
    reps=2,
    insert_barriers=True,
)
ansatz.decompose().draw("mpl")

Output:

Output of the previous code cell

No exemplo acima, a maior porta é a porta Toffoli, que atua em três qubits, tornando o circuito 33 -local. O tipo mais comumente usado de circuitos NN -local são os circuitos 22 -local com portas de rotação de um único qubit e portas de emaranhamento de 22 -qubit.

Vamos criar um circuito 22 -local usando a classe TwoLocal do Qiskit. A sintaxe é a mesma de NLocal, mas há algumas diferenças. Por exemplo, a maioria das portas, como RX, RZ e CNOT, pode ser passada como cadeias de caracteres sem importar as portas ou criar uma instância de Parameter .

from qiskit.circuit.library import TwoLocal

ansatz = TwoLocal(
    num_qubits=5,
    rotation_blocks=["rx", "rz"],
    entanglement_blocks="cx",
    entanglement="linear",
    reps=2,
    insert_barriers=True,
)
ansatz.decompose().draw("mpl")

Output:

Output of the previous code cell

Nesse caso, usamos a distribuição de emaranhamento linear, em que cada qubit é emaranhado com o próximo. Para saber mais sobre outras estratégias, consulte a documentação do site TwoLocal .

SU2 eficiente

efficient_su2 é um circuito eficiente em termos de hardware que consiste em camadas de operações de um único qubit abrangendo SU(2) e CX entanglements. Esse é um padrão heurístico que pode ser usado para preparar funções de onda de teste para algoritmos quânticos variacionais ou como um circuito de classificação para aprendizado de máquina.

from qiskit.circuit.library import efficient_su2

ansatz = efficient_su2(4, su2_gates=["rx", "y"], entanglement="linear", reps=1)
ansatz.decompose().draw("mpl")

Output:

Output of the previous code cell

Abordagens específicas para cada problema

Embora as respostas heurísticas e eficientes de hardware nos ajudem a resolver um problema de forma ingênua, podemos usar o conhecimento específico do problema para restringir nosso espaço de pesquisa de circuitos a um tipo específico. Isso nos ajudará a ganhar velocidade sem perder a precisão em nosso processo de pesquisa.

Otimização

Em um problema de corte máximo, queremos particionar os nós de um gráfico de forma a maximizar o número de arestas entre os nós em grupos diferentes. A partição de corte máximo desejada para o gráfico abaixo é clara: o 0º nó à esquerda deve ser separado do restante dos nós à direita por um corte.

import rustworkx as rx
from rustworkx.visualization import mpl_draw

n = 4
G = rx.PyGraph()
G.add_nodes_from(range(n))
# The edge syntax is (start, end, weight)
edges = [(0, 1, 1.0), (0, 2, 1.0), (0, 3, 1.0), (1, 2, 1.0), (2, 3, 1.0)]
G.add_edges_from(edges)

mpl_draw(
    G, pos=rx.shell_layout(G), with_labels=True, edge_labels=str, node_color="#1192E8"
)

Output:

Output of the previous code cell

Para utilizar o algoritmo QAOA em um problema de corte máximo, precisamos de um Hamiltoniano de Pauli que codifique o custo de forma que o valor de expectativa mínima do operador corresponda ao número máximo de bordas entre os nós em dois grupos diferentes.

Para este exemplo simples, o operador é uma combinação linear de termos com operadores Z em nós conectados por uma borda (lembre-se de que o 0º qubit é o mais à direita): ZZII+IZZI+ZIIZ+IZIZ+IIZZZZII + IZZI + ZIIZ + IZIZ + IIZZ. Depois que o operador é construído, o ansatz para o algoritmo QAOA pode ser facilmente construído usando o circuito QAOAAnsatz da biblioteca de circuitos Qiskit.

# Pre-defined ansatz circuit, operator class and visualization tools
from qiskit.circuit.library import QAOAAnsatz
from qiskit.quantum_info import SparsePauliOp

# Problem to Hamiltonian operator
hamiltonian = SparsePauliOp.from_list(
    [("ZZII", 1), ("IZZI", 1), ("ZIIZ", 1), ("IZIZ", 1), ("IIZZ", 1)]
)
# QAOA ansatz circuit
ansatz = QAOAAnsatz(hamiltonian, reps=2)
# Draw
ansatz.decompose(reps=3).draw("mpl")

Output:

Output of the previous code cell

A imagem anterior ilustra o ansatz em portas básicas para maior clareza. No entanto, ele pode ser expresso em vários níveis de decomposição alterando o argumento reps ou desenhando o circuito sem o método de decomposição. Por exemplo, a representação a seguir mostra diretamente a estrutura QAOA com o valor padrão de representantes, que é reps=1.

ansatz.decompose(reps=2).draw("mpl")

Output:

Output of the previous code cell

Quantum Machine Learning

No aprendizado de máquina, um aplicativo comum é a classificação de dados em duas ou mais categorias. Isso envolve a codificação de um ponto de dados em um mapa de recursos que mapeia vetores de recursos clássicos no espaço de Hilbert quântico. A construção de mapas de recursos quânticos com base em circuitos quânticos parametrizados que são difíceis de simular classicamente é uma etapa importante para obter uma possível vantagem sobre as abordagens clássicas de aprendizado de máquina e é uma área ativa da pesquisa atual.

O site zz_feature_map pode ser usado para criar um circuito parametrizado. Podemos passar nossos pontos de dados para o mapa de recursos ( xx ) e uma forma variacional separada para passar os pesos como parâmetros ( θ\theta ).

from qiskit.circuit.library import zz_feature_map, TwoLocal

data = [0.1, 0.2]

zz_feature_map_reference = zz_feature_map(feature_dimension=2, reps=2)
zz_feature_map_reference = zz_feature_map_reference.assign_parameters(data)

variation_form = TwoLocal(2, ["ry", "rz"], "cz", reps=2)
vqc_ansatz = zz_feature_map_reference.compose(variation_form)
vqc_ansatz.decompose().draw("mpl")

Output:

Output of the previous code cell

Resumo

Com esta lição, você aprendeu a definir seu espaço de pesquisa com uma forma variacional:

  • Preparar estados com um circuito quântico parametrizado, em que as portas são definidas com parâmetros ajustáveis
  • Como criar respostas que compensem a velocidade e a precisão
  • Respostas heurísticas
  • Respostas específicas para problemas

Nossa carga de trabalho variacional de alto nível é a seguinte:

Um diagrama de circuito mostrando dois unitários: um que prepara o estado de referência e outro que prepara o ansatz.

Para cada parâmetro variacional θ\vec\theta, será produzido um estado quântico diferente. Para encontrar os parâmetros ideais, precisamos definir uma função de custo específica do problema para atualizar iterativamente os parâmetros do nosso ansatz.

Esta página foi útil?
Relate um bug, erro de digitação ou solicite conteúdo no GitHub.