Pular para o conteúdo principal

Introdução prática aos critérios de DiVincenzo com Qiskit 2

Introdução

O físico David DiVincenzo descreveu cinco requisitos-chave para qualquer implementação física de um computador quântico, além de dois critérios adicionais para comunicação quântica. Neste notebook, vivenciaremos cada critério de DiVincenzo por meio de demonstrações práticas com Qiskit. Em vez de aprofundarmos na teoria, cada seção explica brevemente um critério e, em seguida, fornece exercícios de código usando Qiskit 2. Você poderá executar circuitos em simuladores e em dispositivos reais IBM Quantum para explorar cada princípio na prática.

Os Cinco Critérios de DiVincenzo para Computação Quântica:

  1. Um sistema físico escalável com qubits bem caracterizados.
  2. Capacidade de inicializar qubits em um estado fiducial simples (por exemplo, |00…0〉).
  3. Tempos de decoerência longos (coerência do qubit muito maior que o tempo de operação da porta).
  4. Um conjunto universal de portas quânticas (capaz de realizar operações unitárias arbitrárias).
  5. Capacidade de medição específica do qubit (ler o estado de cada qubit).

(DiVincenzo também descreveu dois critérios para comunicação quântica: a capacidade de interconverter qubits estacionários e "voadores", e de transmitir fielmente qubits voadores entre locais. Incluímos esses em uma atividade recomendada ao final deste notebook.)

Cada uma das seções a seguir corresponde a um critério. Usaremos Qiskit para ilustrar o conceito com código e experimentos interativos que você pode tentar. Por exemplo, veremos como aumentar o número de qubits e a profundidade do circuito afeta os resultados (Critério 1), como redefinir e preparar estados de qubit (Critério 2), como medir qubits em simuladores vs dispositivos reais (Critério 4), como o Qiskit compõe portas universais (Critério 3) e como a coerência finita (T₁, T₂) impacta os cálculos (Critério 5). Ao final, você terá uma intuição mais profunda sobre o que cada critério de DiVincenzo significa na prática e como o Qiskit permite experimentar com eles.

# Added by doQumentation — required packages for this notebook
!pip install -q numpy
# Install necessary packages
!pip install qiskit[visualization] qiskit-ibm-runtime qiskit-aer qiskit_ibm_runtime

1. Critério 1 – Qubits Escaláveis e Bem Caracterizados

Critério 1: “Um sistema físico escalável com qubits bem caracterizados.” Isso significa que precisamos de uma plataforma de hardware quântico onde possamos aumentar o número de qubits e ainda controlá-los de forma confiável. As propriedades de cada qubit (níveis de energia, taxas de erro, conectividade, etc.) devem ser bem compreendidas. Essencialmente, queremos construir circuitos maiores sem que o sistema falhe. Na prática, à medida que aumentamos a contagem de qubits ou a profundidade do circuito, erros e decoerência se acumulam, então demonstrar a escalabilidade também significa entender como o aumento do tamanho afeta o desempenho.

Objetivo da Demo: Usar o Qiskit para mostrar o efeito de aumentar a escala de um circuito (em contagem de qubits ou profundidade de portas) sobre a fidelidade da saída. Simularemos um cenário ideal vs ruidoso para ver como um sistema maior ou um circuito mais profundo sucumbe à decoerência e a erros.

Primeiro, vamos construir um pequeno estado emaranhado (estado GHZ) em 3 qubits, depois um maior em 5 qubits, como um teste simples de escalabilidade. Um estado GHZ de n qubits é 12(0...0+1...1)\frac{1}{\sqrt{2}}(|0...0\rangle + |1...1\rangle). Em uma simulação ideal, medir um GHZ de n qubits produz apenas dois resultados (todos 0 ou todos 1) com igual probabilidade. Compararemos a saída ideal com uma saída ruidosa à medida que aumentamos n ou a profundidade do circuito.

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import SamplerV2 as Sampler

# 3-qubit GHZ circuit
qc3 = QuantumCircuit(3, 3)
qc3.h(0)
qc3.cx(0, 1)
qc3.cx(1, 2)
qc3.measure([0, 1, 2], [0, 1, 2])

# 5-qubit GHZ circuit (scaling up the number of qubits)
qc5 = QuantumCircuit(5, 5)
qc5.h(0)
qc5.cx(0, range(1, 5)) # entangle qubit 0 with all others
qc5.measure(range(5), range(5))

# Transpile for a simulator backend
sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc3 = pm.run(qc3)
isa_qc5 = pm.run(qc5)

# Run ideal simulations (no noise)
sampler = Sampler(mode=sim_backend)

job3 = sampler.run([isa_qc3], shots=1024)
result3 = job3.result()
counts3 = result3[0].data.c.get_counts()

job5 = sampler.run([isa_qc5], shots=1024)
result5 = job5.result()
counts5 = result5[0].data.c.get_counts()

print("3-qubit GHZ counts (ideal):", counts3)
plot_histogram(counts3, legend=['3-qubit ideal'], figsize=(6,4))
3-qubit GHZ counts (ideal): {'000': 531, '111': 493}

Diagrama do circuito quântico

print("5-qubit GHZ counts (ideal):", counts5)
plot_histogram(counts5, legend=['5-qubit ideal'], figsize=(6,4))
5-qubit GHZ counts (ideal): {'11111': 535, '00000': 489}

Saída do código

Resultado esperado (caso ideal): O GHZ de 3 qubits idealmente produz aproximadamente 50% de 000 e 50% de 111 nas contagens. O GHZ de 5 qubits produz ~50% de 00000 e 50% de 11111. Nenhuma outra cadeia de bits aparece porque o estado é idealmente totalmente coerente e emaranhado. Você deve ver duas barras altas no histograma para cada circuito correspondendo aos resultados de todos-zeros e todos-uns.

A seguir, vamos ver o que acontece em um ambiente ruidoso. Usaremos os recursos de modelo de ruído do Qiskit Aer para imitar os erros de um dispositivo real. Por exemplo, podemos pegar as propriedades de um backend IBM para criar um modelo de ruído que inclui erros de portas, tempos finitos de portas, relaxamento dos qubits (T₁), defasagem (T₂) e erros de leitura. Aqui, usaremos um fake backend que representa o dispositivo IBM Quantum Brisbane para gerar um modelo de ruído e reexecutar os circuitos GHZ por meio dele.

Exercício 1a: Simular com Ruído

Complete o código abaixo para simular os circuitos GHZ em um simulador ruidoso baseado no backend FakeBrisbane. Isto mostrará como o desempenho se degrada à medida que o sistema escala em um ambiente realista de ruído.

from qiskit_ibm_runtime.fake_provider import FakeBrisbane

# We will reuse the ideal circuits qc3 and qc5 and their results from the previous cell.

# --- YOUR CODE HERE ---

# 1. Create a fake backend for IBM Quantum Brisbane
###brisbane_backend = ...

# 2. Create a noisy AerSimulator from the fake backend's properties
###noisy_sim = ...

# 3. Transpile the circuits for the noisy simulator (this adapts them to the device's specific gates and connectivity)
###pm = ...

###isa_qc3_noisy = ...

###isa_qc5_noisy = ...

# 4. Run the noisy simulations using the Sampler and get the counts
###sampler = ...

###job3 = ...

###result3_noisy = ...

###counts3_noisy = ...

###job5 = ...

###result5_noisy = ...

###counts5_noisy = ...

# --- END YOUR CODE ---

# This part is done for you to print and plot the results:
print("3-qubit GHZ counts (noisy):", counts3_noisy)
plot_histogram(counts3_noisy, legend=['3-qubit noisy'], figsize=(6,4))
print("5-qubit GHZ counts (noisy):", counts5_noisy)
plot_histogram(counts5_noisy, legend=['5-qubit noisy'], figsize=(6,4))

Exercício 1b: Executar em um computador IBM Quantum real

O código abaixo executa os circuitos GHZ em um computador IBM Quantum real. Isto mostrará como o desempenho se degrada em um dispositivo real.

# your_api_key = "deleteThisAndPasteYourAPIKeyHere"
# your_crn = "deleteThisAndPasteYourCRNHere"

# QiskitRuntimeService.save_account(
# channel="ibm_quantum_platform",
# token=your_api_key,
# instance=your_crn,
# name="fallfest-2025",
# )

# Check that the account has been saved properly
# service = QiskitRuntimeService(name="fallfest-2025")
# print(service.saved_accounts())

# We will reuse the ideal circuits qc3 and qc5 and their results from the previous cell.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService(name="fallfest-2025")
real_backend = service.least_busy(operational=True, simulator=False)
print("Running on " + real_backend.name)

pm = generate_preset_pass_manager(backend=real_backend, optimization_level=1)
isa_qc3r = pm.run(qc3)
isa_qc5r = pm.run(qc5)

sampler = Sampler(mode=real_backend)

job3r = sampler.run([isa_qc3r], shots=1024)
result3r = job3r.result()
counts3r = result3r[0].data.c.get_counts()

job5r = sampler.run([isa_qc5r], shots=1024)
result5r = job5r.result()
counts5r = result5r[0].data.c.get_counts()

print("3-qubit GHZ counts (real):", counts3r)
plot_histogram(counts3r, legend=['3-qubit real'], figsize=(6,4))
print("5-qubit GHZ counts (real):", counts5r)
plot_histogram(counts5r, legend=['5-qubit real'], figsize=(6,4))

Resultado esperado (ruidoso vs ideal): Com ruído, seja simulado ou em um dispositivo real, o estado GHZ é menos perfeito. Você verá resultados adicionais além de todos-0 e todos-1. Para 3 qubits, em vez de 100% em 000/111, alguma probabilidade vaza para outras cadeias de bits (por exemplo, 001, 010, etc.) devido a erros de porta ou decoerência invertendo alguns qubits. Para 5 qubits, o efeito é ainda mais pronunciado; o circuito maior (mais qubits e portas CNOT) acumula mais erro, então os picos de todos-0 e todos-1 são mais baixos, e muitos outros resultados aparecem. Esta tendência ilustra o desafio da escalabilidade: à medida que escalamos, manter alta fidelidade fica mais difícil sem correção de erros.

Insight: Um computador quântico escalável precisa preservar correlações quânticas à medida que o sistema cresce. Nossos exemplos mostram como aumentar a contagem de qubits/profundidade de portas faz com que a fidelidade do resultado caia quando há ruído presente. Os critérios restantes lidarão com manter esses qubits bem comportados (baixo erro, inicializáveis, etc.) enquanto escalamos.

2. Critério 2 – Inicialização de Qubits

Critério 2: “A capacidade de inicializar o estado dos qubits para um estado fiducial simples, como |000…〉.” Todos os qubits devem começar de forma confiável em um estado de referência conhecido (tipicamente o estado fundamental |0〉 para cada qubit). A inicialização é essencial para que os algoritmos comecem em uma lousa limpa. Na prática, em dispositivos quânticos da IBM, cada qubit é automaticamente redefinido para |0〉 no início de cada execução de circuito. O Qiskit também fornece instruções para redefinir qubits ou preparar estados personalizados durante uma computação.

Objetivo da Demo: Mostrar como inicializar qubits no Qiskit, tanto no início quanto no meio do circuito. Demonstraremos usando a instrução reset e métodos de preparação de estado.

Exercício 2: Preparar um Estado Específico

No bloco de código abaixo, complete o QuantumCircuit para preparar o estado 10|10\rangle. Isso significa que o qubit 0 deve estar no estado 0|0\rangle e o qubit 1 deve estar no estado 1|1\rangle. Use a porta e a instrução apropriadas para conseguir isso.

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator

# Create a circuit to initialize qubits to |10> and verify by measurement
qc_init = QuantumCircuit(2, 2)

# --- YOUR CODE HERE ---

# 1. Set qubit 1 to the |1> state

# 2. Explicitly reset qubit 0 to the |0> state

# --- END YOUR CODE ---

qc_init.measure([0, 1], [0, 1])
qc_init.draw('mpl')
# Run the circuit and check the outcome
sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_init = pm.run(qc_init)

sampler = Sampler(mode=sim_backend)

job = sampler.run([isa_qc_init], shots=1024)
result = job.result()
counts = result[0].data.c.get_counts()

print("Outcome of |10> state measured in Z-basis:", counts)
plot_histogram(counts)

Você deve ver 10 (binário para qubit1=1, qubit0=0) com 100% de probabilidade na simulação, o que significa que o qubit 1 foi preparado com sucesso em |1〉 e o qubit 0 em |0〉.

Agora, para uma preparação de estado mais geral, o Qiskit permite a inicialização para estados arbitrários usando o método initialize. Por exemplo, vamos preparar um qubit no estado +=(0+1)/2|+\rangle = (|0\rangle+|1\rangle)/\sqrt{2}, que é um estado de superposição, e um par de qubits no estado de Bell (00+11)/2(|00\rangle+|11\rangle)/\sqrt{2}:

import numpy as np

# Initialize a single qubit in |+> state and measure in Z-basis
qc_plus = QuantumCircuit(1, 1)
state_plus = [1/np.sqrt(2), 1/np.sqrt(2)] # amplitude for |0> and |1>
qc_plus.initialize(state_plus, 0)
qc_plus.measure(0, 0)

# Initialize two qubits in a Bell state manually
qc_bell = QuantumCircuit(2, 2)
bell_state = [1/np.sqrt(2), 0, 0, 1/np.sqrt(2)] # amplitudes for |00>,|01>,|10>,|11>
qc_bell.initialize(bell_state, [0, 1])
qc_bell.measure([0, 1], [0, 1])

# Transpile and run the initialization circuits
isa_qc_plus = pm.run(qc_plus)
job_plus = sampler.run([isa_qc_plus], shots=1024)
result_plus = job_plus.result()
counts_plus = result_plus[0].data.c.get_counts()

print("Outcome of |+> state measured in Z-basis:", counts_plus)

isa_qc_bell = pm.run(qc_bell)
job_bell = sampler.run([isa_qc_bell], shots=1024)
result_bell = job_bell.result()
counts_bell = result_bell[0].data.c.get_counts()

print("Outcome of Bell state measured in Z-basis:", counts_bell)
Outcome of |+> state measured in Z-basis: {'1': 499, '0': 525}
Outcome of Bell state measured in Z-basis: {'00': 508, '11': 516}

Resultados esperados: O estado |+〉 de um único qubit, quando medido, produzirá 0 e 1 com aproximadamente 50% de probabilidade cada. A medição do estado de Bell deve fornecer aproximadamente 50% de 00 e 50% de 11. Se você observar isso, confirma que nossa inicialização para esses estados foi bem-sucedida.

Inicialização no meio do circuito: O reset do Qiskit pode ser usado no meio de um circuito para reinicializar um qubit para |0〉 dinamicamente. Por exemplo, em códigos de correção de erros ou algoritmos iterativos, frequentemente se mede um qubit e depois o redefine para reutilização. A operação reset é determinística; ela descarta qualquer estado existente e resfria o qubit ao estado fundamental.

Exemplo de dispositivo: Em hardware como ibmq_brisbane (127 qubits) ou qualquer dispositivo IBM, todos os qubits começam em |0〉 por padrão quando uma tarefa é executada. Se você precisasse de um estado inicial diferente, aplicaria portas no início (como fizemos com X para obter |1〉). A reinicialização contínua (para correção quântica de erros) é um tópico de pesquisa ativo porque fazê-la rapidamente é desafiador. Felizmente, para uso básico, a capacidade de começar do zero em |0…0〉 está disponível e demonstramos como obter outros estados iniciais desejados também.

3. Critério 3 – Tempo Longo de Coerência (Decoerência vs Tempo de Porta)

Critério 3: “Tempos de decoerência relevantes longos, muito maiores que o tempo de operação da porta.” Isto aborda a necessidade de os qubits manterem seu estado quântico por tempo suficiente para realizar as operações necessárias. Cada qubit possui um tempo T₁ (tempo de relaxamento de energia, quão rapidamente |1〉 decai para |0〉) e um tempo T₂ (tempo de defasagem, quão rapidamente a coerência de fase relativa é perdida). Para que um computador quântico funcione, essas escalas de tempo devem exceder em muito a duração das operações de porta.

Objetivo da Demo: Investigar a coerência dos qubits no Qiskit mostrando como a decoerência impacta os resultados dos circuitos à medida que o comprimento de execução cresce. Usaremos um fake backend com tempos T1/T2 conhecidos para simular esse efeito.

Para demonstrar o impacto da coerência finita, simularemos um experimento de decaimento T1. Prepararemos um qubit no estado |1〉, esperaremos algum tempo usando uma instrução delay e depois mediremos. Esperamos que a probabilidade de medir |1〉 diminua à medida que o atraso aumenta.

# This part is done for you. We are creating a list of circuits,
# each with a different delay time.

time_delays_ns = [0, 50000, 100000, 150000, 200000, 250000, 300000] # delay durations in ns

decay_expts = []
for delay in time_delays_ns:
qc = QuantumCircuit(1, 1)
qc.x(0) # initialize qubit to |1>
if delay > 0:
qc.delay(delay, 0, unit='ns') # wait 'delay' nanoseconds
qc.measure(0, 0)
decay_expts.append(qc)

decay_expts[1].draw('mpl') # Visualize one of the circuits

Diagrama do circuito quântico

Exercício 3: Simular um Experimento de Decaimento T1

Agora, use um simulador ruidoso baseado em FakeVigo (que tem tempos T1 de ~50-100 µs) para executar esses circuitos. O simulador aplicará automaticamente os erros T1/T2 durante as instruções delay. Transpile os circuitos para este backend e execute-os.

from qiskit_ibm_runtime.fake_provider import FakeVigoV2 as FakeVigo
from qiskit_aer import AerSimulator

# --- YOUR CODE HERE ---

# 1. Create a noisy simulator from the FakeVigo backend
###sim_vigo = ...

# 2. Transpile the list of circuits for this simulator
###pm = ...

###isa_decay_expts = ...

# 3. Use the Sampler to run all the transpiled circuits in a single job
###sampler = ...

###job = ...

###result = ...

# --- END YOUR CODE ---

# This part is done for you to analyze and print the results.
for idx, (delay, qc) in enumerate(zip(time_delays_ns, isa_decay_expts)):
counts = result[idx].data.c.get_counts()
p1 = counts.get('1', 0) / 1000 # Assuming 1000 shots
print(f"Delay {delay} ns: P(qubit=1) = {p1:.3f}")

4. Critério 4 – Conjunto Universal de Portas Quânticas

Critério 4: “Um conjunto ‘universal’ de portas quânticas.” Isso significa que nosso hardware deve nos permitir realizar qualquer computação quântica compondo um conjunto finito de portas básicas. Na computação clássica, NAND é universal; em quântica, há muitas opções de conjuntos universais de portas (por exemplo, {H, T, CNOT} ou as portas nativas de uma determinada máquina). Os dispositivos da IBM, por exemplo, têm um conjunto de operações nativas como rotações arbitrárias de qubit único e CNOTs entre certos qubits, que juntos são universais. O trabalho do Qiskit é frequentemente compilar portas de alto nível nessas portas básicas.

Objetivo da Demo: Ilustrar a universalidade das portas mostrando como o Qiskit decompõe portas. Pegaremos uma porta não nativa (como uma porta Toffoli de 3 qubits, CCX) e veremos como ela se decompõe nas portas básicas do dispositivo. Isto demonstra que o conjunto de portas fornecido é de fato universal – ele pode produzir a operação mais complexa.

Primeiro, vamos ver quais são as portas básicas para um backend IBM típico. Consultaremos a configuração de um dispositivo (ou sua versão fake). Por exemplo, as portas básicas do ibmq_brisbane: Você deve observar a probabilidade P(qubit=1) diminuindo à medida que o tempo de atraso aumenta, seguindo uma curva de decaimento exponencial característica do relaxamento T1. Isso demonstra diretamente como o tempo de coerência finito leva a erros computacionais se o circuito for executado por muito tempo.

Impacto nos algoritmos: Se você tentar um algoritmo mais longo (com muitas portas sequenciais), o tempo total de execução pode se aproximar ou exceder T2, fazendo com que o estado perca a coerência antes do final. É por isso que melhorar os tempos de coerência e tornar as portas mais rápidas são dois dos objetivos mais críticos na pesquisa de hardware quântico.

from qiskit_ibm_runtime.fake_provider import FakeBrisbane
fake_brisbane = FakeBrisbane()
print("Basis gates for ibmq_brisbane:", fake_brisbane.configuration().basis_gates)
Basis gates for ibmq_brisbane: ['ecr', 'id', 'rz', 'sx', 'x']

Isso pode produzir algo como ['id', 'rz', 'sx', 'x', 'ecr']. Estas são as operações primitivas que o hardware suporta nativamente (Identidade/no-op, rotação RZ, porta sqrt(X), porta X e X controlada). Qualquer outra porta deve ser composta a partir destas. Sabe-se que este conjunto é universal para a computação quântica (essencialmente rotações de qubit único mais uma porta de dois qubits emaranhante formam um conjunto universal).

Agora, considere uma porta Toffoli (CCX) como caso de teste. CCX inverte um qubit alvo somente se dois qubits de controle forem ambos 1. Não é uma porta nativa no hardware da IBM. O Qiskit fornece uma instrução ccx, mas internamente ela será decomposta.

Exercício 4: Decompor uma Porta Toffoli

Complete o código abaixo para construir um circuito com uma porta Toffoli (CCX) e então use o Qiskit para decompô-la nas portas básicas nativas do backend FakeBrisbane.

from qiskit import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeBrisbane

# The fake_brisbane backend from the previous cell is reused here.

# --- YOUR CODE HERE ---

# 1. Create a circuit that can accommodate a Toffoli gate
###qc_toffoli = ...

# Apply a CCX gate with controls on qubits 0, 1 and target on qubit 2

# 2. Transpile the circuit to the fake Brisbane backend
###pm = ...

###isa_qc_toffoli = ...

# --- END YOUR CODE ---

print("Toffoli circuit before decomposition:")
print(qc_toffoli)

print("\nToffoli circuit after transpiling to Brisbane basis:")
# The .draw() method will now show the decomposed circuit
print(isa_qc_toffoli.draw(fold=120))

Na saída transpilada, você deve ver o CCX substituído por uma sequência de portas mais básicas como rz, sx e ecr. Isto comprova que as portas nativas são suficientes para expressar a Toffoli.

Universalidade na prática: O exercício acima mostra que uma porta complexa de 3 qubits foi construída a partir de outras mais simples. Em geral, qualquer unitária de múltiplos qubits pode ser composta a partir de portas de 1 e 2 qubits. O transpilador é um componente crucial de qualquer pilha de software quântico, pois faz a ponte entre os algoritmos abstratos que queremos executar e as operações físicas que um dispositivo quântico específico pode realmente realizar.

Exemplo de dispositivo: O dispositivo ibmq_brisbane usa a arquitetura Eagle com as portas básicas mostradas acima. Isso significa que qualquer algoritmo enviado para essas máquinas será convertido em sequências dessas operações. Este critério é essencialmente sobre controlabilidade; temos botões de controle suficientes para fazer qualquer operação necessária em nossos qubits.

5. Critério 5 – Medição de Qubit

Critério 5: “Uma capacidade de medição específica do qubit.” O estado de cada qubit deve ser mensurável (tipicamente na base computacional, |0〉 ou |1〉). Em outras palavras, após executar um circuito quântico, precisamos ler cada qubit como um bit clássico 0/1. Este critério é sobre ter detectores confiáveis para cada qubit e ser capaz de selecionar quais qubits medir.

Objetivo da Demo: Mostrar como realizar medições no Qiskit em simuladores e dispositivos reais e destacar as diferenças (como ruído de medição). Mediremos alguns qubits em vários estados e examinaremos os resultados. Também demonstraremos como erros de leitura podem aparecer comparando resultados do simulador vs hardware.

Primeiro, um exemplo simples de medição:

qc_measure = QuantumCircuit(2, 2)
qc_measure.x(0) # qubit 0 -> |1>, qubit 1 stays |0>
qc_measure.measure([0, 1], [0, 1])
qc_measure.draw('mpl')

Diagrama do circuito quântico

sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_measure = pm.run(qc_measure)
job = sampler.run([isa_qc_measure], shots=1000)
result = job.result()
counts = result[0].data.c.get_counts()

print("Simulator measurement counts:", counts)
Simulator measurement counts: {'01': 1000}

Esperamos 1000 contagens de 01 no simulador. Agora, vamos ver o erro de medição em ação simulando-o. Podemos adicionar um erro de leitura ao nosso simulador Aer. O Qiskit Aer permite definir um ReadoutError e anexá-lo aos qubits em um modelo de ruído.

Exercício 5: Simular Erro de Leitura

Complete o código para definir um modelo simples de erro de leitura onde cada qubit tem 2% de chance de ser medido incorretamente (um 0 é lido como 1, ou um 1 como 0). Em seguida, execute o circuito de medição com este modelo de ruído.

from qiskit_aer.noise import NoiseModel, ReadoutError

# --- YOUR CODE HERE ---

# 1. Define a 2% readout error for each single qubit.
# The format is a list of lists of probabilities: [[P(0|0), P(1|0)], [P(0|1), P(1|1)]]
# P(A|B) is the probability of measuring A given the state was |B>.
###ro_error = ...

# 2. Create a new noise model
###noise_model_ro = ...

# 3. Add the readout error to all qubits in the noise model
... # Hint: Use the add_all_qubit_readout_error method

# --- END YOUR CODE ---

sim_backend.set_options(noise_model=noise_model_ro)
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_measure = pm.run(qc_measure)

# Run the measurement circuit with readout noise
sampler = Sampler(mode=sim_backend)

job = sampler.run([isa_qc_measure], shots=1024)
result = job.result()
counts = result[0].data.c.get_counts()

print("Simulation with 2% readout error:", counts)

Esta saída simulada mostrará algumas contagens errôneas (como 11, 00, 10) similares ao que o hardware real poderia produzir, demonstrando o impacto de uma medição imperfeita.

Exemplo de dispositivo: Em um dispositivo real como ibmq_brisbane, você poderia executar o mesmo circuito e provavelmente veria contagens não nulas similares para os resultados incorretos. Os dados de calibração do dispositivo listam um erro de leitura para cada qubit. Ser capaz de mirar e ler qubits específicos é crucial, e entender suas características de erro é fundamental para obter resultados significativos. A execução em um dispositivo real foi demonstrada em Exercício 1b: Executar em um computador IBM Quantum real.

Critérios de Comunicação Quântica (Qubits Voadores)

DiVincenzo também listou dois critérios específicos para a comunicação quântica, importantes ao construir um computador quântico em rede:

  1. Capacidade de interconverter qubits estacionários e voadores. (Por exemplo, mapear um qubit em um processador para um fóton que pode viajar.)
  2. Capacidade de transmitir fielmente qubits voadores entre locais. (Por exemplo, enviar um qubit-fóton através de uma fibra sem perder informação quântica.)

Esses estão além do uso padrão do Qiskit, pois o Qiskit lida principalmente com qubits estacionários em um chip. No entanto, podemos ilustrar o conceito desses critérios com um exemplo simples: teletransporte quântico. O teletransporte mostra a conversão do estado de um qubit estacionário em informações carregadas por um par emaranhado (a parte "voadora") e comunicação clássica, que é então usada para reconstruir o estado em outro qubit estacionário em outro lugar.

O módulo Teletransporte Quântico do Qiskit in Classrooms, da Dra. Katie McCormick, irá guiá-lo por um dos protocolos mais cativantes da informação quântica: o teletransporte quântico, em que um estado quântico (um qubit) é enviado de Alice para Bob usando emaranhamento e apenas dois bits clássicos. Você aprenderá o procedimento completo de teletransporte passo a passo — como preparar o par emaranhado de Bell, realizar uma medição na base de Bell do lado de Alice, transmitir os resultados clássicos e aplicar a porta quântica correta no qubit de Bob para recuperar perfeitamente o estado original. Ao longo do caminho, você explorará por que teletransportar a informação de um qubit não viola o teorema da não-clonagem nem excede a velocidade da luz. Por meio de exercícios práticos usando hardware ou simuladores IBM Quantum, você adquirirá uma compreensão prática de medição, emaranhamento e controle feed-forward em ação.

Ao dominar o teletransporte quântico, você entenderá como codificar, transmitir e recuperar informação quântica entre nós distintos — lançando as bases para redes quânticas, sistemas de repetidores, esquemas de comunicação seguros e computação quântica modular escalável. Como isto se relaciona com os critérios 6 & 7: Em uma rede quântica real, o par emaranhado compartilhado seria criado distribuindo qubits "voadores" (como fótons) entre as localizações de Alice e Bob (Critério 7: transmissão fiel). O próprio protocolo de teletransporte serve então como uma forma de mapear o estado do qubit estacionário de Alice em sua metade do par emaranhado, efetivamente 'enviando-o' para Bob (Critério 6: interconversão). O Qiskit nos permite simular a lógica do protocolo perfeitamente, fornecendo um modelo conceitual de como esses critérios são atendidos em arquiteturas de comunicação.

Conclusão & Resumo

Projetamos uma série de exercícios focados em código para ilustrar os critérios de DiVincenzo usando Qiskit. Por meio desses exemplos práticos, você explorou como uma plataforma real de computação quântica atende a cada requisito:

  • Escalabilidade: construir circuitos em mais qubits e entender o escalonamento do ruído.
  • Inicialização: usar resets e preparação de estado para iniciar computações de forma confiável em estados conhecidos.
  • Portas Universais: transpilar operações complexas para as portas básicas de uma máquina, provando que podemos realizar qualquer computação.
  • Medição: ler qubits e lidar com erros realistas de leitura.
  • Coerência: ver o efeito de T₁, T₂ finitos sobre a fidelidade do algoritmo e a necessidade de operações serem rápidas em relação à decoerência.

Para completar, também abordamos aspectos da comunicação quântica por meio do módulo Teletransporte Quântico do Qiskit in Classrooms, conectando os dois últimos critérios (qubits voadores).

Por fim, vale notar como esses critérios se reúnem em um computador quântico real como o da IBM. Um dispositivo como ibmq_brisbane tem 127 qubits supercondutores (Critério 1), cada um começando em |0〉 (Critério 2), com conjunto de portas calibrado e compiladores para universalidade (Critério 4), ressonadores de leitura por micro-ondas para cada qubit (Critério 5) e tempos de coerência da ordem de centenas de microssegundos vs operações em nanossegundos (Critério 3). Para experimentos de redes quânticas, a IBM e outros estão explorando a transdução de micro-ondas para óptica para qubits voadores, e o emaranhamento de qubits distantes (Critérios 6 & 7); essas são áreas de pesquisa ativa.