Portuguese, Brazilian
Idiomas
English
Japanese
German
Korean
Portuguese, Brazilian
French
Shortcuts

Nota

Esta página foi gerada, a partir do tutorials/algorithms/06_qaoa.ipynb.

Execute interativamente no IBM Quantum lab.

Algoritmo De Otimização Quântica Aproximada

O Qiskit possui uma implementação do algoritmo de otimização quântica aproximada QAOA e este notebook demonstra a sua utilização para um problema de partição de grafos.

Embora o QAOA pode ser utilizado diretamente, é muitas vezes mais conveniente usá-lo em conjunto com o módulo Optimization. Veja os tutoriais de Optimization para obter mais informações.

[1]:
import numpy as np
import networkx as nx

from qiskit import BasicAer
from qiskit.aqua.algorithms import NumPyMinimumEigensolver
from qiskit.optimization.applications.ising import graph_partition
from qiskit.optimization.applications.ising.common import random_graph, sample_most_likely

Primeiro criamos um grafo aleatório e o desenhamos para que ele possa ser visto.

[2]:
num_nodes = 4
w = random_graph(num_nodes, edge_prob=0.8, weight_range=10, seed=48)
print(w)
[[ 0. -5. -6.  0.]
 [-5.  0. -2.  5.]
 [-6. -2.  0.  4.]
 [ 0.  5.  4.  0.]]
[3]:
G = nx.from_numpy_matrix(w)
layout = nx.random_layout(G, seed=10)
colors = ['r', 'g', 'b', 'y']
nx.draw(G, layout, node_color=colors)
labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos=layout, edge_labels=labels);
../../_images/tutorials_algorithms_06_qaoa_4_0.png

O método exaustivo é o seguinte. Basicamente, tentamos exaustivamente todas as atribuições binárias. Em cada atribuição binária, a entrada de um vértice é ou 0 (significando que o vértice está na primeira partição) ou 1 (ou seja, o vértice está na segunda partição). Nós imprimimos a atribuição binária que satisfaz a definição da partição do gráfico e que corresponde ao número mínimo de arestas de cruzamento.

[4]:
def brute_force():
    # use the brute-force way to generate the oracle
    def bitfield(n, L):
        result = np.binary_repr(n, L)
        return [int(digit) for digit in result]  # [2:] to chop off the "0b" part

    L = num_nodes
    max = 2**L
    minimal_v = np.inf
    for i in range(max):
        cur = bitfield(i, L)

        how_many_nonzero = np.count_nonzero(cur)
        if how_many_nonzero * 2 != L:  # not balanced
            continue

        cur_v = graph_partition.objective_value(np.array(cur), w)
        if cur_v < minimal_v:
            minimal_v = cur_v
    return minimal_v

sol = brute_force()
print(f'Objective value computed by the brute-force method is {sol}')
Objective value computed by the brute-force method is 3

The graph partition problem can be converted to an Ising Hamiltonian. Qiskit has different capabilities in the Optimization module to do this. Here, since the goal is to show QAOA, the module is used without further explanation to create the operator. The paper Ising formulations of many NP problems may be of interest if you would like to understand the technique further.

[5]:
qubit_op, offset = graph_partition.get_operator(w)

Então vamos usar o algoritmo de QAOA para encontrar a solução.

[6]:
from qiskit.aqua import aqua_globals
from qiskit.aqua.algorithms import QAOA
from qiskit.aqua.components.optimizers import COBYLA
from qiskit.circuit.library import TwoLocal

aqua_globals.random_seed = 10598

optimizer = COBYLA()
qaoa = QAOA(qubit_op, optimizer, quantum_instance=BasicAer.get_backend('statevector_simulator'))

result = qaoa.compute_minimum_eigenvalue()

x = sample_most_likely(result.eigenstate)
ising_sol = graph_partition.get_graph_solution(x)

print(ising_sol)
print(f'Objective value computed by QAOA is {graph_partition.objective_value(x, w)}')
[0. 0. 1. 1.]
Objective value computed by QAOA is 3.0

Pode-se ver que o resultado está de acordo com o valor calculado acima exaustivamente. Mas também podemos usar o NumPyMinimumEigensolver clássico para fazer a computação, que pode ser útil como referência sem fazer as coisas exaustivamente.

[7]:
npme = NumPyMinimumEigensolver(qubit_op)
result = npme.compute_minimum_eigenvalue()

x = sample_most_likely(result.eigenstate)
ising_sol = graph_partition.get_graph_solution(x)

print(ising_sol)
print(f'Objective value computed by the NumPyMinimumEigensolver is {graph_partition.objective_value(x, w)}')
[0 0 1 1]
Objective value computed by the NumPyMinimumEigensolver is 3

Também é possível utilizar o VQE como é mostrado abaixo

[8]:
from qiskit.aqua.algorithms import VQE
from qiskit.circuit.library import TwoLocal

aqua_globals.random_seed = 10598

optimizer = COBYLA()
var_form = TwoLocal(qubit_op.num_qubits, 'ry', 'cz', reps=5, entanglement='linear')
vqe = VQE(qubit_op, var_form, optimizer, quantum_instance=BasicAer.get_backend('statevector_simulator'))

result = vqe.compute_minimum_eigenvalue()

x = sample_most_likely(result.eigenstate)
ising_sol = graph_partition.get_graph_solution(x)

print(ising_sol)
print(f'Objective value computed by VQE is {graph_partition.objective_value(x, w)}')
[0. 1. 0. 1.]
Objective value computed by VQE is 3.0
[9]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
Qiskit0.23.0
Terra0.16.0
Aer0.7.0
Ignis0.5.0
Aqua0.8.0
IBM Q Provider0.11.0
System information
Python3.6.1 |Continuum Analytics, Inc.| (default, May 11 2017, 13:09:58) [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]
OSLinux
CPUs1
Memory (Gb)5.827335357666016
Sun Nov 08 19:24:06 2020 EST

This code is a part of Qiskit

© Copyright IBM 2017, 2020.

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.