Nota
Esta página foi gerada a partir de tutorials/algorithms/01_algorithms_introduction.ipynb.
Execute interativamente no IBM Quantum lab.
Uma introdução aos Algoritmos no Qiskit¶
Esta é uma introdução aos algoritmos no Qiskit e fornece uma visão geral de alto nível para ajudar a entender os vários aspectos da funcionalidade a ser iniciado. Outros tutoriais fornecerão material mais aprofundado, sobre os algoritmos, e formas de usá-los, etc.
Como a biblioteca de algoritmos está estruturada?¶
O Qiskit fornece um número de Algoritmos e eles estão agrupados por categoria de acordo com a tarefa que eles podem executar. Por exemplo, Minimum Eigensolvers
para encontrar o menor valor eigen de um operador, por exemplo, a energia subterrânea da química Hamiltoniana ou uma solução para um problema de otimização quando expressa como Ising Hamiltonian. Existem Classifiers
para problemas de classificação de machine learning e Amplitude Estimator
para estimativa de valor que pode ser usada por exemplo em aplicações financeiras. O conjunto completo de categorias pode ser visto no link acima, com a documentação dos Algoritmos.
Algoritmos são configuráveis e muitas vezes, parte da configuração estará na forma de blocos de construção menores, dos quais, diferentes instâncias do tipo bloco de construção podem ser fornecidas. Por exemplo, com VQE
, o Variacional Quantum Eigensolver, precisa de uma função de onda experimental, na forma de um QuantumCircuit
e um otimizador clássico entre outras coisas. Tais blocos de construção podem ser encontrados como Components e como circuitos da Circuit Library.
Vamos dar uma olhada em um exemplo para construir uma instância de VQE. Aqui TwoLocal
é a forma variacional (versão de ondas de teste), um circuito parametrizado que pode ser variado e SLSQP
um otimizador clássico. Estas são criadas como instâncias separadas e transmitidas para o VQE quando este for construído. Tentando, por exemplo, um otimizador clássico diferente, ou forma variacional é simplesmente um caso de criação de uma instância da que você deseja e a passagem para o VQE.
[1]:
from qiskit.aqua.algorithms import VQE
from qiskit.aqua.components.optimizers import SLSQP
from qiskit.circuit.library import TwoLocal
num_qubits = 2
ansatz = TwoLocal(num_qubits, 'ry', 'cz')
opt = SLSQP(maxiter=1000)
vqe = VQE(var_form=ansatz, optimizer=opt)
Vamos desenhar o ansatz para que possamos ver que é um QuantumCircuit onde[0] através de θ[7] serão os parâmetros variados conforme o otimizador do VQE encontrar o eigenvalue mínimo. Voltaremos aos parâmetros mais tarde, abaixo, em um exemplo funcional.
[2]:
ansatz.draw()
[2]:

Mas é necessário mais antes de podermos executar o algoritmo, então vamos em frente.
Como executar um algoritmo?¶
Para executar um algoritmo precisamos ter um simulador ou dispositivo real no backend, sobre o qual os circuitos que compreendem o algoritmo podem ser executados. Assim, por exemplo, podemos usar o statevector_simulator
do provedor BasicAer.
[3]:
from qiskit import BasicAer
backend = BasicAer.get_backend('statevector_simulator')
Agora, um backend por conta própria não tem informações sobre como você executaria os circuitos etc. Por exemplo quantos shots, se você quer um modelo de ruído ou até mesmo opções de transpiling nos circuitos. Para este Qiskit Aqua, existe um QuantumInstance fornecendo tanto o backend como também várias configurações em torno do processamento do circuito e execução, assim por exemplo:
[4]:
from qiskit.aqua import QuantumInstance
backend = BasicAer.get_backend('qasm_simulator')
quantum_instance = QuantumInstance(backend=backend, shots=800, seed_simulator=99)
Nota: se você fornecer o backend diretamente então internamente ums QuantumInstance será criado a partir dele, com configurações padrão, para que os algoritmos trabalhem todo o tempo através de uma QuantumInstance.
Então agora nós poderíamos chamar o método run(), que é comum a todos os algoritmos e retorna um resultado específico para o algoritmo. Neste caso, uma vez que o VQE é um minimumEigensolver nós poderíamos usar o método compute_mininum_eigenvalue(). Este método é a interface escolhida para os módulos de aplicação, como Química e Otimização, para que eles possam funcionar de forma recíproca com qualquer algoritmo dentro da categoria específica.
Um exemplo de trabalho completo¶
Let’s put what we have learned from above together and create a complete working example. VQE will find the minimum eigenvalue, i.e. minimum energy value of a Hamiltonian operator and hence we need such an operator for VQE to work with. Such an operator is given below. This was originally created by the Chemistry application module as the Hamiltonian for an H2 molecule at 0.735A interatomic distance. It’s a sum of Pauli terms as below, but for now I am not going to say anything further about it since the goal is to run the algorithm, but further information on operators can be found in other tutorials.
[5]:
from qiskit.aqua.operators import X, Z, I
H2_op = (-1.052373245772859 * I ^ I) + \
(0.39793742484318045 * I ^ Z) + \
(-0.39793742484318045 * Z ^ I) + \
(-0.01128010425623538 * Z ^ Z) + \
(0.18093119978423156 * X ^ X)
Então vamos construir uma instância VQE passando o operador e um backend, usando um QuantumInstance, para a construtora. Agora o VQE tem setters para que o operador e backend também possam ser passados mais tarde. Fixá-las posteriormente pode ser útil ao criar um algoritmo sem que este problema tenha informações específicas e depois, posteriormente, utilizá-lo, digamos com o módulo de aplicação de química, o qual criaria o operador para o problema específico de química ser resolvido.
Nota: Para que você possa executar este notebook e ver o resultado exato, o gerador de números aleatórios usado em toda a Aqua em aqua_globals, assim como o transpiler e o simulador, através da QuantumInstance precisa ser usado. Você não precisa fazer isso, mas se quiser ser capaz de reproduzir exatamente o mesmo resultado toda vez, então é assim que se faz.
Então, vamos executar o VQE e imprimir o resultado que ele retorna.
[6]:
from qiskit.aqua import aqua_globals
seed = 50
aqua_globals.random_seed = seed
qi = QuantumInstance(BasicAer.get_backend('statevector_simulator'), seed_transpiler=seed, seed_simulator=seed)
ansatz = TwoLocal(rotation_blocks='ry', entanglement_blocks='cz')
slsqp = SLSQP(maxiter=1000)
vqe = VQE(operator=H2_op, var_form=ansatz, optimizer=slsqp, quantum_instance=qi)
result = vqe.run()
import pprint
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(result)
{ 'cost_function_evals': 72,
'eigenstate': array([-9.55448660e-05+2.12037105e-17j, 9.93766273e-01+2.25293943e-16j,
-1.11483565e-01+1.52657541e-16j, -1.77521351e-05+3.71607315e-17j]),
'eigenvalue': (-1.857275017559769+0j),
'optimal_parameters': { Parameter(θ[0]): 4.296520551468743,
Parameter(θ[1]): 4.426962086704216,
Parameter(θ[2]): 0.5470753710293924,
Parameter(θ[7]): 0.3602072316165878,
Parameter(θ[6]): -4.717618235040379,
Parameter(θ[5]): 1.5683261371389359,
Parameter(θ[3]): 6.09294789784282,
Parameter(θ[4]): -2.598325857134344},
'optimal_point': array([ 4.29652055, 4.42696209, 0.54707537, 6.0929479 , -2.59832586,
1.56832614, -4.71761824, 0.36020723]),
'optimal_value': -1.857275017559769,
'optimizer_evals': 72,
'optimizer_time': 1.310880184173584}
Do resultado acima nós podemos ver que o otimizador 72
foi levado pelas avaliações dos valores dos parâmetros até que ele encontre o valor minimum eigenvalue of -1.85727
que é a energia eletrônica do estado fundamental da molécula H2 indicada. Os parâmetros ideais do ansatz também podem ser vistos, que são os valores que estavam nos ansatz com valor mínimo.
Usando VQE como um MinimumEigensolver¶
Para finalizar vamos usar a interface MinimumEigensolver e também criar uma instância de VQE sem fornecer o operador ou o QuantumInstance. Posteriormente, definimos a instância QuantumInstance e finalmente passamos o operador no método compute_minimum_eigenvalue
(embora ao invés disso, pudéssemos tê-lo passado mais cedo através do setter, desde que no momento de executar o VQE, ele tenha um operador para trabalhar).
[7]:
aqua_globals.random_seed = seed
qi = QuantumInstance(BasicAer.get_backend('statevector_simulator'), seed_transpiler=seed, seed_simulator=seed)
ansatz = TwoLocal(rotation_blocks='ry', entanglement_blocks='cz')
slsqp = SLSQP(maxiter=1000)
vqe = VQE(var_form=ansatz, optimizer=slsqp)
vqe.quantum_instance = qi
result = vqe.compute_minimum_eigenvalue(operator=H2_op)
pp.pprint(result)
{ 'cost_function_evals': 72,
'eigenstate': array([-9.55448660e-05+2.12037105e-17j, 9.93766273e-01+2.25293943e-16j,
-1.11483565e-01+1.52657541e-16j, -1.77521351e-05+3.71607315e-17j]),
'eigenvalue': (-1.857275017559769+0j),
'optimal_parameters': { Parameter(θ[4]): -2.598325857134344,
Parameter(θ[5]): 1.5683261371389359,
Parameter(θ[6]): -4.717618235040379,
Parameter(θ[7]): 0.3602072316165878,
Parameter(θ[1]): 4.426962086704216,
Parameter(θ[0]): 4.296520551468743,
Parameter(θ[2]): 0.5470753710293924,
Parameter(θ[3]): 6.09294789784282},
'optimal_point': array([ 4.29652055, 4.42696209, 0.54707537, 6.0929479 , -2.59832586,
1.56832614, -4.71761824, 0.36020723]),
'optimal_value': -1.857275017559769,
'optimizer_evals': 72,
'optimizer_time': 2.8010470867156982}
Uma vez que a semeadura idêntica foi utilizada como exemplo prévio, o resultado pode ser visto como o mesmo.
Isso conclui essa introdução aos algoritmos no Qiskit. Confira os outros tutoriais de algoritmos nesta série para uma cobertura mais ampla e mais profunda dos algoritmos.
[8]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
Qiskit | 0.23.1 |
Terra | 0.16.1 |
Aer | 0.7.1 |
Ignis | 0.5.1 |
Aqua | 0.8.1 |
IBM Q Provider | 0.11.1 |
System information | |
Python | 3.7.8 | packaged by conda-forge | (default, Jul 31 2020, 02:25:08) [GCC 7.5.0] |
OS | Linux |
CPUs | 8 |
Memory (Gb) | 31.40900421142578 |
Fri Jan 15 12:11:24 2021 UTC |
This code is a part of Qiskit
© Copyright IBM 2017, 2021.
This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.
[ ]: