Skip to main content
IBM Quantum Platform

Simulação eficiente de circuitos estabilizadores com primitivas Qiskit Aer

  • O código desta página foi desenvolvido usando os seguintes requisitos. Recomendamos o uso dessas versões ou de versões mais recentes.

    qiskit[all]~=2.5.0
    qiskit-aer~=0.17
    

Esta página mostra como usar as primitivas do Qiskit Aer para simular com eficiência os circuitos estabilizadores, inclusive aqueles sujeitos ao ruído Pauli.

Os circuitos estabilizadores, também conhecidos como circuitos de Clifford, são uma importante classe restrita de circuitos quânticos que podem ser simulados classicamente de forma eficiente. Há várias maneiras equivalentes de definir circuitos estabilizadores. Uma definição é que um circuito estabilizador é um circuito quântico que consiste apenas nas seguintes portas:

Observe que, usando Hadamard e S, podemos construir qualquer porta de rotação Pauli ( RxR_x, RyR_y, e RzR_z ) que tenha um ângulo contido no conjunto {0,π2,π,3π2}\{0, \frac{\pi}{2}, \pi, \frac{3\pi}{2}\} (até a fase global), portanto, também podemos incluir essas portas na definição.

Os circuitos estabilizadores são importantes para o estudo da correção de erros quânticos. Sua capacidade de simulação clássica também os torna úteis para verificar a saída de computadores quânticos. Por exemplo, suponha que você queira executar um circuito quântico que usa 100 qubits em um computador quântico. Como você sabe que o computador quântico está se comportando corretamente? Um circuito quântico de 100 qubits está além do alcance da simulação clássica de força bruta. Ao modificar seu circuito para que ele se torne um circuito estabilizador, é possível executar circuitos no computador quântico que tenham uma estrutura semelhante à do circuito desejado, mas que possam ser simulados em um computador clássico. Ao verificar a saída do computador quântico nos circuitos estabilizadores, você pode ter certeza de que ele está se comportando corretamente também nos circuitos não estabilizadores. Consulte Evidência da utilidade da computação quântica antes da tolerância a falhas para obter um exemplo dessa ideia na prática.

A simulação exata e com ruído com primitivos do Qiskit Aer mostra como usar o Qiskit Aer para realizar simulações exatas e com ruído de circuitos quânticos genéricos. Considere o circuito de exemplo usado nesse artigo, um circuito de 8 qubits construído usando efficient_su2 :

from qiskit.circuit.library import efficient_su2

n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")

Output:

Output of the previous code cell

Usando o Qiskit Aer, conseguimos simular esse circuito com facilidade. No entanto, suponha que definimos o número de qubits como 500:

n_qubits = 500
circuit = efficient_su2(n_qubits)
# don't try to draw the circuit because it's too large

Como o custo da simulação de circuitos quânticos aumenta exponencialmente com o número de qubits, um circuito tão grande geralmente excede os recursos até mesmo de um simulador de alto desempenho como o Qiskit Aer. A simulação clássica de circuitos quânticos genéricos torna-se inviável quando o número de qubits excede aproximadamente 50 a 100 qubits. Entretanto, observe que o circuito efficient_su2 é parametrizado por ângulos nos portões RyR_y e RzR_z. Se todos esses ângulos estiverem contidos no conjunto {0,π2,π,3π2}\{0, \frac{\pi}{2}, \pi, \frac{3\pi}{2}\}, então o circuito é um circuito estabilizador e pode ser simulado com eficiência!

Na célula a seguir, executamos o circuito com o primitivo Sampler apoiado pelo simulador de circuito estabilizador, usando parâmetros escolhidos aleatoriamente, de modo que o circuito seja garantidamente um circuito estabilizador.

import numpy as np
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import SamplerV2 as Sampler

measured_circuit = circuit.copy()
measured_circuit.measure_all()

rng = np.random.default_rng(1234)
params = rng.choice(
    [0, np.pi / 2, np.pi, 3 * np.pi / 2],
    size=circuit.num_parameters,
)

# Initialize a Sampler backed by the stabilizer circuit simulator
exact_sampler = Sampler(
    options=dict(backend_options=dict(method="stabilizer"))
)
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(
    1, AerSimulator(method="stabilizer")
)
isa_circuit = pass_manager.run(measured_circuit)
pub = (isa_circuit, params)
job = exact_sampler.run([pub])
result = job.result()
pub_result = result[0]
counts = pub_result.data.meas.get_counts()

O simulador de circuito estabilizador também suporta simulação com ruído, mas somente para uma classe restrita de modelos de ruído. Especificamente, qualquer ruído quântico deve ser caracterizado por um canal de erro Pauli. O erro de despolarização se enquadra nessa categoria, portanto, também pode ser simulado. Os canais de ruído clássicos, como o erro de leitura, também podem ser simulados.

A célula de código a seguir executa a mesma simulação anterior, mas, desta vez, especificando um modelo de ruído que adiciona um erro de despolarização de 2% a cada porta CX, bem como um erro de leitura que inverte cada bit medido com 5% de probabilidade.

from qiskit_aer.noise import NoiseModel, depolarizing_error, ReadoutError

noise_model = NoiseModel()
cx_depolarizing_prob = 0.02
bit_flip_prob = 0.05
noise_model.add_all_qubit_quantum_error(
    depolarizing_error(cx_depolarizing_prob, 2), ["cx"]
)
noise_model.add_all_qubit_readout_error(
    ReadoutError(
        [
            [1 - bit_flip_prob, bit_flip_prob],
            [bit_flip_prob, 1 - bit_flip_prob],
        ]
    )
)

noisy_sampler = Sampler(
    options=dict(
        backend_options=dict(method="stabilizer", noise_model=noise_model)
    )
)
job = noisy_sampler.run([pub])
result = job.result()
pub_result = result[0]
counts = pub_result.data.meas.get_counts()

Agora, vamos usar a primitiva Estimator com o apoio do simulador de estabilizador para calcular o valor esperado do observável ZZZZZ \cdots Z. Devido à estrutura especial dos circuitos estabilizadores, é muito provável que o resultado seja 0.

from qiskit.quantum_info import SparsePauliOp
from qiskit_aer.primitives import EstimatorV2 as Estimator

observable = SparsePauliOp("Z" * n_qubits)

exact_estimator = Estimator(
    options=dict(backend_options=dict(method="stabilizer")),
)
isa_circuit = pass_manager.run(circuit)
pub = (isa_circuit, observable, params)
job = exact_estimator.run([pub])
result = job.result()
pub_result = result[0]
exact_value = float(pub_result.data.evs)
exact_value

Output:

0.0

Próximas etapas

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