Computação Quântica: Introdução ao Pacote Qiskit e Algoritmo de Grover

Cláudio Alves Monteiro
6 min readMay 20, 2020

--

Aqui neste tutorial vamos ver com executar circuitos quânticos usando pacote Qiskit e implementar o Algoritmo de Grover para amplificação de probabilidade de estados quânticos. Para acompanhar as explicações é necessário ter uma base de como funciona a computação quântica e quais são seus operadores principais. Fique à vontade para ver o post anterior que fiz e que explica essa fundamentação, ou siga abaixo caso já conheça.

Introdução ao Pacote Qiskit

Fonte: https://github.com/Qiskit/qiskit

O Qiskit é um framework open-source desenvolvido pela IBM para trabalhar com computadores quânticos no desenvolvimento de circuitos e algoritmos. Como um pacote da linguagem Python, o Qiskit permite uma integração com código Python que facilita muito a construção de algoritmos, dada a simplicidade da sintaxe e a comum necessidade de se executar parte dos algoritmos classicamente [1]. Para instalar o pacote, basta executar pip install qiskit no terminal, para mais informações acesse o site oficial.

Seguindo a documentação do Qiskit, o processo de desenvolvimento de um sistema quântico envolve 3 passos em alto nível: (1) Construir e desenhar o circuito quântico que representa o problema em consideração; (2) Executar os experimentos, que podem rodar em simuladores na sua própria máquina ou em computadores quânticos reais (ainda que ruidosos) da IBM; e por fim (3) Analisar e calcular as estatísticas dos resultados e visualizar as saídas dos experimentos. Abaixo vamos seguir um simples workflow para ver o que acontece quando colocamos 2 qubits em superposição e os mensuramos.

#===================                       
# INICIALIZACAO
#=================
# importar pacotes
from qiskit import QuantumCircuit, execute, Aer
# definir uso do simulador Aer qasm
simulator = Aer.get_backend('qasm_simulator')
#======================
# CONSTRUIR CIRCUITO
#====================
# criar um circuito quantico com 2 quits
# e duas mensuracoes (qubit, measurements)
circuit = QuantumCircuit(2, 2)
# aplicar um hadamard no qubit 0 e outro no qubit 1
circuit.h(0)
circuit.h(1)
# mapear a mensuracao aos bits classicos
# ([qubitX, qubitY], [measureX, measureY])
circuit.measure([0,1], [0,1])
# visualizar circuito
circuit.draw(output='mpl')

Acima é possível observar um Hadamard aplicado em cada qubit e depois uma mensuração em cada um deles. Como vimos anteriormente, nesse caso teremos o sistema |ψ〉 = α1β1|00〉+ α1β2|01〉+ β1α2|10〉+ β1β2|11〉. Espera-se que cada estado tenha uma distribuição de probabilidade semelhante. Vamos testar a execução deste circuito no Aer, um simulador do qiskit que roda na sua própria máquina. Vale salientar que o número de shots é que vai nos trazer essa distribuição de probabilidade, pois o quando executamos a mensuração o sistema colapsa para uma das quatro possibilidades dos estados quânticos.

#=====================================                       
# EXECUCAO E ANALISE DOS RESULTADOS
#===================================
# importar funcao de visualizacao
from qiskit.visualization import plot_histogram
# executar circuito no simulador 1000 vezes
job = execute(circuit, simulator, shots=1000)
# salvar resultados da execucao
result = job.result()
# retornar contagem
counts = result.get_counts(circuit)
print(counts)

{‘00’: 253, ‘01’: 239, ‘10’: 242, ‘11’: 266}

# visualizar no grafico
plot_histogram(counts)
Fonte: elaboração própria a partir do pacote Qiskit

É possível observar os estados quânticos com suas respectivas probabilidades, semelhantes, porém não iguais devido ao numero de shots que quanto maior ele é, maior será a aproximação entre as probabilidades dos estados. Em seguida vamos estudar o Algoritmo de Grover e seus fundamentos, bem como executá-lo com o pacote qiskit.

Algoritmo de Grover

Imagine que precisamos achar um contato numa lista no seu celular sem saber em que ordem eles estão. Na computação clássica podemos fazer uma busca um por um até achar o contato que queremos, ou uma abordagem mais eficiente seria sortear aleatoriamente a posição de busca. Nessa última abordagem vamos precisa verificar em média N/2 posições para encontrar o contato. O Algoritmo de Grover se utiliza da propriedade de superposição para resolver esse problema em O √N, o que apresenta um ganho significativo em relação à abordagem clássica [2]. Por exemplo, se tivéssemos uma lista com 102400 informações, para achar no computador clássico levaria até 51200 passos enquanto no computador quântico levaria até 320 passos. O algoritmo se dá da seguinte forma:

  1. Colocamos os qubits em superposição para expandir os estados quânticos;
  2. Aplicamos a inversão de fase com base num oráculo, que vai marcar o estado quântico que estamos procurando;
  3. Aplicamos a inversão sobre a média, também chamada de reflexão, para amplificar a probabilidade do estado procurado. Esse passo é executado O √N vezes;
  4. Por fim, mensuramos o qubits e esperamos encontrar o estado quântico procurado com alta probabilidade.
Circuito do algoritmo de Grover para 2 qubits. Fonte: Qiskit

Acima se encontra o circuito do algoritmo de Grover para 2 qubits. Abaixo vamos observar como os estados quânticos evoluem à medida que os operadores quânticos são aplicados. No |ψ0〉os qubits são inicializados no estado 0 e em |ψ1〉se aplica a porta de Hadamard para expandir os estados.

|ψ2〉,|ψ3〉 e |ψ4〉representam as portas aplicadas no oráculo para inversão de fase do estado que se busca:

|ψ5〉se refere aos Hadamards aplicados após o oráculo:

|ψ6〉, |ψ7〉e |ψ8〉se referem à reflexão, que fazem a inversão sobre a média do estado |00〉:

Agora que entendemos a matemática por trás do algoritmo de Grover, vamos implementar e executar o circuito com o pacote qiskit.

#======================                       
# CONSTRUIR CIRCUITO
#====================
# criar um circuito quantico com 2 quits
# e duas mensuracoes (qubit, measurements)
nq = 2
circuito_grover_ = QuantumCircuit(nq, 2)
# aplicar hadamard nos qubits [psi 1]
for qubit in range(nq):
circuito_grover_.h(qubit)
#=================
# ORACULO
#================
# aplicar not nos qubits [psi 2]
for qubit in range(nq):
circuito_grover_.x(qubit)
# aplicar Z no qubit 1 controlado pelo qubit 0 [psi 3]
circuito_grover_.cz(0, 1)
# aplicar not nos qubits [psi 2]
for qubit in range(nq):
circuito_grover_.x(qubit)
# visualizar circuito
circuito_grover_.draw('mpl')
Oráculo
#=================
# REFLEXAO
#================
# hadamard em cada qubit
for qubit in range(nq):
circuito_grover_.h(qubit)
# reflexao
for qubit in range(nq):
circuito_grover_.z(qubit)
circuito_grover_.cz(0, 1)
# hadamard em cada qubit
for qubit in range(nq):
circuito_grover_.h(qubit)
#======================
# mensurar qubits
#====================
circuito_grover_.measure([0,1], [0,1])#visualizar circuito
circuito_grover_.draw('mpl')
Grover
#=====================================                       
# EXECUCAO E ANALISE DOS RESULTADOS
#===================================
# importar funcao de visualizacao
from qiskit.visualization import plot_histogram
# executar circuito no simulador 1000 vezes
job = execute(circuito_grover_, simulator, shots=1000)
# salvar resultados da execucao
result = job.result()
# retornar contagem
counts = result.get_counts(circuito_grover_)
print(counts)

{‘00’: 1000}

# visualizar no grafico
plot_histogram(counts)

Acima é possível observar a ação do circuito que amplia a probabilidade do estado marcado. Com isso podemos começar a compreender o funcionamento dessas máquinas, que podem representar e processar informações em estados de superposição, que crescem a uma ordem de 2^N, ou seja, num computador quântico de 30 qubits temos 2³⁰, o que resulta em mais de 1 bilhão de estados quânticos em superposição. A ideia é que dentre alguns anos teremos computadores com qubits suficientes para processar grandes volumes de dados, resolver problemas combinatórios, quebrar criptografias e etc.

Essa foi uma introdução à computação quântica, na qual pudemos ver uma simples aplicação que faz uso de suas propriedades. O Algoritmo de Grover serve como base para outros trabalhos que envolvem otimização e buscas em espaços multidimensionais, servindo como ponto de partida para algoritmos mais complexos. Aqui também agradeço ao meu orientador no mestrado, Fernando Neto, professor do departamento de Ciência da Computação da UFPE, pela revisão do tutorial.

Referências

[1] H. A. et al, “Qiskit: An open-source framework for quantum computing,”2019

[2] Grover, Lov K. “A fast quantum mechanical algorithm for database search.” Proceedings of the twenty-eighth annual ACM symposium on Theory of computing. 1996.

--

--