RESUMO EM CONSTRUÇÃO
Chips compõem-se bilhões de transistores (semicondutores microscópicos que controlam fluxo de elétrons binários - não passa energia é 0, passa energia é 1). Em 1975, Gordon Moore, cofundador da Intel, observou que quantidade de transistores em chip de circuito integrado dobra aproximadamente a cada 2 anos (Lei de Moore), resultando chips menores e mais rápidos. Atualmente, transistores de silício chegaram à escala de nanômetros, com dimensões próximas ao tamanho de átomos individuais (miniaturização extrema). Ocasionará problemas físicos em túnel quântico (tunelamento quântico - elétrons começam atravessar barreiras microscópicas, causando vazamentos de corrente), aquecimento (quanto mais transistores, mais calor, limitando desempenho), custo e energia. Computação clássica está chegando ao limite físico do silício (espaço físico para encolher e acelerar chips está fisicamente lotado - problema do caixeiro-viajante). Moore prevê tal limite em meados de 2025.
Chip de processamento quântico é minúsculo (muitas vezes menor que moeda), mas necessita de grande sistema de suporte para funcionamento íntegro, pois qubits são extremamente sensíveis (qualquer calor, luz, som ou vibração pode destruir o estado quântico). Planos que compõem hardware quântico:
Sequência de portas quânticas usadas em cálculo.
Computação quântica complementará coexistência a computação clássica (integração híbrida), pois dispositivos computacionais ainda utilizam demais componentes de interpretação binária clássica. Computação quântica é utilizada em longos processamentos de dados, como descriptografia, pesquisas científicas, simulações moleculares, IAs avançadas, etc. Criptografia pós-quântica (PQC), novos algoritmos clássicos resistentes a ataques quânticos e clássicos, são desenvolvidos como resposta à ameaça da computação quântica. Distribuição quântica de chaves (QKD) é baseada em princípios quânticos para comunicação inviolável. Protocolo BB84 permite criar chave secreta entre 2 partes. Tentativas de espionagem alteram estados quânticos e são detectadas. Problemas de otimização em finanças e engenharia, onde computação quântica, via algoritmos QAOA ou recozimento quântico, pode encontrar soluções melhores e mais rápidas para problema do caixeiro-viajante, roteamento de veículos, e otimização de cadeias de suprimentos.
Método alternativo ao modelo de portas, usado para resolver problemas de otimização e amostragem. Busca estado de energia mínima de sistema físico representando problema. Qubits evoluem de superposição inicial para configuração final, usando tunelamento quântico para atravessar barreiras de energia e evitar ótimos locais, aumentando chance de alcançar solução global. Aplicações incluem otimização combinatória, finanças, rotas e machine learning. Problema da não linearidade, na aprendizagem clássica, ocorre quando métodos lineares não captam relações complexas. No ML quântico, embora operações sejam lineares, feature maps introduzem não linearidades eficazes. Circuitos variacionais (VQC) com portas parametrizadas aprendem funções altamente não lineares, semelhantes a redes neurais profundas.
Átomo de Rydberg corresponde a átomo excitado que possui, em média, 1 ou mais elétrons distantes do núcleo. Átomos de Rydberg têm várias propriedades peculiares, incluindo resposta exagerada a campos elétricos e magnéticos, bem como vida longa. Quando usados como qubits, oferecem interações atômicas fortes e controláveis ajustáveis ao selecionar diferentes estados.
Dado quântico armazenado nos spins nucleares dos átomos em moléculas, e portas lógicas manipulam essa informação via radiação eletromagnética. Pósitron ou elétron podem ter spin 'para cima', 'para baixo', ou ambos simultaneamente, representando estados do qubit. Momentos magnéticos nucleares fazem movimento natural de precessão na presença de campos magnéticos. Estados quânticos dos núcleos podem ser manipulados irradiando núcleos com pulsos de rádio frequência sintonizados na frequência de precessão dos mesmos.
Ato de transformar possibilidade (superposição) em realidade (0 ou 1). Qubits estão constantemente em superposição (probabilidades % de estar em 0 à 1), e tornam-se definidos (0 ou 1) após medição. Exemplo, em superposição, um qubit pode estar 70% em 0 e 30% em 1, mas após medição será 0 ou 1.
Esparçador Pauli (Sparse Pauli) adventa matrizes de Pauli, onde são aplicadas 3 matrizes X, Y e Z em, além de I (identidade I), em um qubit, para medir seu estado.
Em 3 qubits, operação X ⊗ Z ⊗ I (ou "XZI" - Pauli String, sequência de Paulis) aplica X no qubit 1, Z no qubit 2, e I (nada) no qubit 3. SparsePauliOp (Sparse Pauli Operator) é forma compacta (esparsa) de guardar combinações sem ocupar tanta memória. Estado quântico é "como sistema está", SparsePauli é "tipo de óculos com que você observa". Você escolhe "conjunto de lentes" (matrizes Pauli) para olhar seu sistema e obter informações (medições). Pauli noise (ruído de Pauli) é um modelo de ruído quântico que descreve erros aleatórios aplicados a qubits usando matrizes de Pauli (X, Y, Z). Usadas para simular imperfeições reais nas transformações de qubits, em computadores quânticos. X-error inverte estado (Bit-flip noise), Z-error muda fase (Phase-flip noise), e Y-error combina erros X e Z (inversão + mudança de fase, Bit-phase-flip noise). Depolarizing noise destaca forma simétrica de Pauli noise na aplicação de X, Y ou Z com mesma probabilidade.
Avaliam desempenho e utilidade dos computadores quânticos, sem implicar vantagem comprovada sobre métodos clássicos. Fidelidade de camada mede capacidade geral do processador em executar circuitos, revelando detalhes sobre qubits, portas e interferências. CLOPS (operações de camada de circuito por segundo) mede velocidade de execução de circuitos de volume quântico, combinando desempenho quântico e clássico. Ambas permitem comparar sistemas e acompanhar ganhos de performance. Profundidade do circuito indica quantas operações paralelas podem ser executadas antes da decoerência, determinando complexidade dos circuitos possíveis.
Linguagens utilizadas especificamente para processamento quântico. Ambientes disponíveis para desenvolvimento são IBM Quantum Experience, Azure Quantum, Google Quantum AI e AWS Braket. Plataformas IBM Quantum Platform, Azure Quantum, Google Quantum AI e AWS Braket oferecem ferramentas e recursos para desenvolvimento quântico.
open Microsoft.Quantum.Intrinsic; // Importa operações quânticas básicas
open Microsoft.Quantum.Measurement; // Importa operações de medição
open Microsoft.Quantum.Canon; // Importa operações canônicas
operation CreateBellPair() : (Result, Result) {
use qubits = Qubit[2]; // Aloca array de 2 qubits
H(qubits[0]); // Aplica porta quântica Hadamard no 1º qubit (superposição)
CNOT(qubits[0], qubits[1]); // Aplica porta quântica CNOT (Controlled-NOT, entrelaçamento)
let result1 = M(qubits[0]); // Mede 1º qubit
let result2 = M(qubits[1]); // Mede 2º qubit
Reset(qubits[0]); // Reseta 1º qubit
Reset(qubits[1]); // Reseta 2º qubit
return (result1, result2); // Retorna resultados das medições (sempre iguais, exemplo, ambos 0 ou ambos 1)
}
pip3 install qiskit qiskit-ibm-runtime matplotlib qiskit[visualization] jupyter
from qiskit_ibm_runtime import QiskitRuntimeService
QiskitRuntimeService.save_account(
channel="ibm_quantum_platform",
token="SEU-TOKEN-IBM-QUANTUM-AQUI",
overwrite=True
) # Usar apenas 1 vez para salvar conta
service = QiskitRuntimeService() # Usar para conectar conta em cada script
print("Conta conectada com sucesso!")
# Instalar runtime (via terminal): pip3 install qiskit qiskit-ibm-runtime matplotlib qiskit[visualization] jupyter
# Conexão com IBM Quantum (única vez no ambiente):
from qiskit_ibm_runtime import QiskitRuntimeService
QiskitRuntimeService.save_account(token="SEU-TOKEN-IBM-QUANTUM-AQUI")
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import EstimatorV2 as Estimator, QiskitRuntimeService
service = QiskitRuntimeService() # Conecta conta IBM Quantum, utilizar em cada script
qc = QuantumCircuit(2) # Cria circuito quântico com 2 qubits
qc.h(0) # Aplica porta Hadamard no qubit 0 (superposição)
qc.cx(0, 1) # Aplica porta CNOT (CX) com qubit 0 controlando qubit 1 (entrelaçamento)
qc.measure_all() # Mede todos qubits
qc.draw("mpl") # Desenha circuito
print(qc)
from qiskit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService() # Conectar conta IBM Quantum
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_state_qsphere, plot_bloch_multivector
import matplotlib.pyplot as plt
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
ghz = QuantumCircuit(3) # Circuito com 3 qubits
ghz.h(0) # Hadamard (colocar qubit 0 em superposição)
ghz.cx(0, 1) # CNOT (entrelaçar qubit 0 com qubit 1)
ghz.cx(0, 2) # CNOT (entrelaçar qubit 0 com qubit 2)
print("Circuito GHZ (desenho em texto):")
print(ghz.draw("text")) # Qubits entrelaçados em estado GHZ
state_ghz = Statevector.from_instruction(ghz) # Vetor de estado do circuito GHZ
print("Vetor de estado GHZ resultante:")
print(state_ghz)
# Visualização QSphere — mostra amplitudes e fases
fig = plot_state_qsphere(state_ghz)
fig.figure.savefig("ghz_qsphere.png")
plt.imshow(fig.figure.canvas.renderer.buffer_rgba())
plt.show() # Estados com diferentes pesos/amplitudes em lados opostos da esfera, mas com mesma fase em coerência quântica (superposição coerente) e fase relativa zero entre eles
# Visualização nos vetores de Bloch dos qubits individuais
fig = plot_bloch_multivector(state_ghz)
fig.figure.savefig("ghz_bloch.png")
plt.imshow(fig.figure.canvas.renderer.buffer_rgba())
plt.show() # Cada qubit individualmente está em estado misto (completamente indefinido), mas sistema global está em estado puro GHZ entrelaçado
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_state_qsphere, plot_bloch_multivector
import matplotlib.pyplot as plt
import math
import numpy as np
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
w_vec = np.array([0, 1, 1, 0, 1, 0, 0, 0], dtype=complex) / math.sqrt(3) # Vetor de estado W de 3 qubits, onde |001>, |010>, |100> têm amplitude 1/√3
w = QuantumCircuit(3, name="W_state") # Circuito de 3 qubits em estado W
w.initialize(w_vec, [0, 1, 2]) # Inicializa 3 qubits no vetor w_vec
print("Circuito W (desenho em texto):")
print(w.draw("text"))
print("Circuito W (desenho em Matplotlib):")
fig = w.draw("mpl")
fig.savefig("w_circuit.png")
plt.imshow(fig.canvas.renderer.buffer_rgba())
plt.axis("off")
plt.show()
# QSphere: amplitudes e fases (3 bases computacionais têm amplitude diferente de zero, todas iguais a 1√3 ≈ 0.577)
fig = plot_state_qsphere(Statevector.from_instruction(w))
fig.figure.savefig("w_qsphere.png")
plt.imshow(fig.figure.canvas.renderer.buffer_rgba())
plt.axis("off")
plt.show()
# Bloch multivector: vetores de Bloch dos qubits individuais (3 qubits estão em estados individuais mistos, não puros)
# Chance de ser 1 (seta para baixo): Qubit só é 1 em 1 dos 3 termos da superposição, probabilidade = 1/3 (≅ 33%)
# Chance de ser 0 (seta para cima): Qubit é "0" nos outros 2 termos, probabilidade = 2/3 (≅ 67%)
fig2 = plot_bloch_multivector(Statevector.from_instruction(w))
fig2.figure.savefig("w_bloch.png")
plt.imshow(fig2.figure.canvas.renderer.buffer_rgba())
plt.axis("off")
plt.show()
# pip3 install qiskit qiskit-ibm-runtime qiskit-aer matplotlib qiskit[visualization]
# pip3 install qiskit-aer
from qiskit_ibm_runtime import QiskitRuntimeService
# QiskitRuntimeService.save_account(token="SEU_TOKEN_AQUI")
import math
import numpy as np
import matplotlib.pyplot as plt
from qiskit import QuantumCircuit, transpile
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_state_qsphere, plot_bloch_multivector
from qiskit_aer import AerSimulator
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
def show_fig(fig):
fig.figure.savefig("tmp_fig.png")
plt.imshow(fig.figure.canvas.renderer.buffer_rgba())
plt.axis("off")
plt.show()
qc_super = QuantumCircuit(1, name="superposition") # Superposição básica
qc_super.h(0) # Hadamard cria superposição (|0> + |1>)/√2
print("Circuito superposição (Hadamard):")
print(qc_super.draw("text"))
fig = qc_super.draw(output="mpl")
show_fig(fig)
# Vetor de estado resultante (sem medida)
state = Statevector.from_instruction(qc_super)
fig_qs = plot_state_qsphere(state)
show_fig(fig_qs)
fig_bloch = plot_bloch_multivector(state)
show_fig(fig_bloch) # Bloch sphere, onde porta H leva |0> ao equador (positivo, superposição igual de |0> e |1>)
# Interferência básica HZH vs HIH
qc_id = QuantumCircuit(1, name="H-I-H") # circuito identidade (identidade não altera estado)
qc_id.h(0)
qc_id.h(0)
qc_z = QuantumCircuit(1, name="H-Z-H") # circuito com interferência de fase Z no meio
qc_z.h(0)
qc_z.z(0)
qc_z.h(0)
print("Circuito H-I-H (texto):")
print(qc_id.draw("text"))
print("Circuito H-Z-H (texto):")
print(qc_z.draw("text"))
state_id = Statevector.from_instruction(qc_id) # vetor de estado H-I-H
state_z = Statevector.from_instruction(qc_z) # vetor de estado H-Z-H
print("Vetor de estado (H-I-H):", state_id.data)
print("Vetor de estado (H-Z-H):", state_z.data)
fig_z = plot_state_qsphere(state_z) # QSphere para H-Z-H (mostra interferência causada pela porta Z, seta para baixo, informando +1 em |1>)
show_fig(fig_z)
fig_z_bloch = plot_bloch_multivector(state_z) # Bloch para H-Z-H (mostra que estado final é |1>, devido à interferência destrutiva em |0>)
show_fig(fig_z_bloch)
sim = AerSimulator() # Simulador local de medições (sem ruído) para validar probabilidades
qc_meas = QuantumCircuit(1,1) # Medição do circuito original de superposição
qc_meas.h(0)
qc_meas.measure(0,0)
qc_id_meas = qc_id.copy() # Medições para H-I-H e H-Z-H
qc_id_meas.measure_all()
qc_z_meas = qc_z.copy()
qc_z_meas.measure_all()
for circuit, name in [(qc_meas, "H"), (qc_id_meas, "H-I-H"), (qc_z_meas, "H-Z-H")]: # Compile e execute (shots)
t_qc = transpile(circuit, sim)
result = sim.run(t_qc, shots=1024).result()
print(f"\nContagens ({name}): {result.get_counts()}")
# H cria superposição (|0> + |1>)/√2, amplitudes iguais, medições ~50/50
# H-I-H é identidade, retorna |0>
# H-Z-H muda fase via aplicação de Z, interferindo e invertendo, cancelando |0> e reforçando |1>
# Medições confirmam probabilidades calculadas pelo vetor de estado
# O simulador rodou 1024 vezes, sendo 0 (522 vezes) e 1 (502 vezes). Portanto, ~50% para 0 e ~50% para 1
# Em H-I-H, resultado foi 0 (1024 vezes) e 1 (0 vezes), confirmando identidade
# Em H-Z-H, resultado foi 1 (1024 vezes) e 0 (0 vezes), confirmando interferência que inverteu estado de |0> para |1>
1º algoritmo quântico da história. Resolve problema de Deutsch em etapa única, via computação quântica. Dada função 'f:{0,1}->{0,1}', queremos saber se a mesma é constante (f(0) = f(1)) ou balanceada (f(0) ≠ f(1)).
A solução, na física clássica, avaliam-se ambas f(0) e f(1). Na física quântica, avaliam-se simultaneamente, via superposição e interferência, em única resposta (diferente de paralelismo clássico), extraindo propriedades da função, não valores individuais. Oráculo é função escondida que algoritmo pode invocar, onde sabe-se apenas quais entradas e saídas, não seu código interno. Algoritmo quântico resolve Deutsch com apenas 1 consulta ao oráculo. Superposição avalia f(0) e f(1) simultaneamente, enquanto Interferência elimina resultados inúteis. Medição estratégica extrai propriedade global da função. Função constante resulta em estado |0⟩, enquanto função balanceada resulta em estado |1⟩.
# pip3 install qiskit qiskit-ibm-runtime qiskit-aer matplotlib qiskit[visualization]
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit import QuantumCircuit, transpile
from qiskit_aer import Aer, AerSimulator
QiskitRuntimeService.save_account(token="SEU_TOKEN_AQUI")
# Função oráculo, cria circuito quântico de função clássica f: {0,1} -> {0,1}
def deutsch_function(case: int):
# case 1: f(x) = 0 (constante)
# case 2: f(x) = x (balanceada)
# case 3: f(x) = ¬x (balanceada)
# case 4: f(x) = 1 (constante)
if case not in [1, 2, 3, 4]:
raise ValueError("`case` must be 1, 2, 3, or 4.")
f = QuantumCircuit(2) # circuito quântico de 2 qubits (1 de entrada, 1 de saída)
if case in [2, 3]:
f.cx(0, 1) # CNOT (f(x) = x ou f(x) = ¬x)
if case in [3, 4]:
f.x(1) # NOT (f(x) = ¬x ou f(x) = 1)
return f
# Exemplo (case 3): f(x) = ¬x (balanceada)
display(deutsch_function(3).draw(output="mpl"))
# q0 (qubit de entrada): |0⟩ ou |1⟩
# q1 (qubit de saída): |1⟩ (inicializado em |1⟩ para permitir interferência)
# Porta CNOT aplicada de q0 para q1 (inverte q1 se q0 for |1⟩)
# Porta X (NOT) aplicada em q1 (inverte q1)
# Resultado final: f(0) = 1 e f(1) = 0
def compile_circuit(function: QuantumCircuit):
n = function.num_qubits - 1
qc = QuantumCircuit(n + 1, n) # n qubits de entrada + 1 qubit de saída
qc.x(n) # Porta X em qubit de saída (inicializa em |1⟩)
qc.h(range(n + 1)) # Portas Hadamard em todos qubits (superposição, exceto saída. q0 é superposição de |0⟩ e |1⟩ simultaneamente
qc.barrier()
qc.compose(function, inplace=True) # Oráculo quântico (CNOT + X), Porta CNOT (q0 é controle, q1 é alvo). Se q0 = 1 então q1 é invertido, se q0 = 0 então nada acontece. Porta X em q1 (inverte q1)
qc.barrier()
qc.h(range(n)) # Porta Hadamard em q0 (interferência - interferência construtiva em |0⟩, interferência destrutiva em |1⟩)
qc.measure(range(n), range(n)) # Medição dos qubits de entrada q0 (resultado: 0 = constante, 1 = balanceada)
return qc
# Exemplo de compilação do circuito Deutsch para f(x) = ¬x (case 3). c é bit clássico, resultado da medição
display(compile_circuit(deutsch_function(3)).draw(output="mpl"))
# Algoritmo de Deutsch, determina se função é constante (0) ou balanceada (1)
def deutsch_algorithm(function: QuantumCircuit):
qc = compile_circuit(function)
result = AerSimulator().run(qc, shots=1, memory=True).result()
measurements = result.get_memory()
if measurements[0] == "0":
return "constant"
return "balanced"
f = deutsch_function(3)
display(deutsch_algorithm(f))
Expansão do algoritmo de Deutsch para funções com múltiplos qubits de entrada, determinando se função é constante ou balanceada via única consulta ao oráculo. Deutsch estipula categorizações de funções quando qubits de entrada n for 0 ou 1. Para valores n maiores que 1, Deutsch-Jozsa considera entradas "indiferentes", sendo promessas de constante ou balanceada.
Após aplicar portas Hadamard (superposição) nos qubits de entrada, aplicação de 2ª camada de portas Hadamard alterarão estado quântico dos qubits de entrada.
# pip3 install qiskit qiskit-ibm-runtime qiskit-aer matplotlib qiskit[visualization]
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit import QuantumCircuit, transpile
from qiskit_aer import Aer, AerSimulator
from qiskit.visualization import plot_histogram
from IPython.display import display
QiskitRuntimeService.save_account(token="SEU_TOKEN_AQUI")
# Função oráculo para Deutsch-Jozsa
def deutsch_jozsa_oracle(n, oracle_type="balanced"):
oracle = QuantumCircuit(n + 1) # n qubits de entrada + 1 qubit auxiliar de saída (fase)
if oracle_type == "constant": # Se função é constante (f(x) = 0), então nada ocorre
pass
elif oracle_type == "balanced": # Se função é balanceada (f(x) = 1 para metade dos inputs), então aplica CX (portas CNOTs para cada qubit, invertendo estado do qubit auxiliar)
for qubit in range(n):
oracle.cx(qubit, n)
return oracle
# Construir circuito Deutsch-Jozsa
def deutsch_jozsa_circuit(n, oracle):
qc = QuantumCircuit(n + 1, n) # n qubits de entrada + 1 qubit auxiliar de saída + n bits clássicos para medição
# Colocar qubit auxiliar em |1>
qc.x(n) # Aplica porta X (NOT) no qubit auxiliar
qc.h(n) # Aplica porta Hadamard no qubit auxiliar
# Aplica porta Hadamard nos qubits de entrada
for qubit in range(n):
qc.h(qubit)
qc.barrier()
qc.compose(oracle, inplace=True) # Aplica oráculo ao circuito
qc.barrier()
# Aplica 2ª camada de portas Hadamard nos qubits de entrada
for qubit in range(n):
qc.h(qubit)
# Mede qubits de entrada nos bits clássicos correspondentes
for qubit in range(n):
qc.measure(qubit, qubit)
return qc
n = 3 # Quantidade de qubits de entrada
oracle_type = "balanced" # Tipo de função ('constant' ou 'balanced')
oracle = deutsch_jozsa_oracle(n, oracle_type) # Cria oráculo
qc = deutsch_jozsa_circuit(n, oracle) # Cria circuito Deutsch-Jozsa
display(qc.draw(output="mpl"))
simulator = Aer.get_backend("aer_simulator") # Usa simulador AER
compiled = transpile(qc, simulator) # Transpila circuito para backend do simulador
result = simulator.run(compiled, shots=1024).result() # Executa circuito no simulador
counts = result.get_counts() # Obtém resultados da medição
display(plot_histogram(counts))
print("Resultados:", counts) # Exibe resultados da medição (000 indica função constante, qualquer outro resultado indica função balanceada)
Elaborado por Mateus Schwede
ubsocial.github.io