[PYTHON] Qiskit: Implémentation de QAOA sans Qiskit Aqua

introduction

Dans mon premier article, j'ai posté j'ai essayé de résoudre TSP avec QAOA. Cependant, cela a utilisé une version dite modulaire de qiskit aqua, ce qui est possible sans avoir à concevoir le circuit vous-même. Donc cette fois, j'aimerais utiliser QAOA sans utiliser qiskit aqua. Tout d'abord, utilisez max cut comme première étape. Pour être honnête, je pense que d'autres problèmes peuvent être résolus simplement en changeant le hamiltonien, donc j'espère que ce sera une référence pour ceux qui font de la programmation quantique avec qiskit. Il existe plusieurs sites qui expliquent la programmation quantique en japonais, mais comme ils utilisent tous des langages de programmation quantique différents, je pense que mon article écrit en qiskit est également significatif.

Dans cet article également, je voudrais expliquer le code de qiskit, en supposant que l'explication de QAOA elle-même sera laissée à d'autres personnes.

Référence: Quantum Native Dojo

code

Tout d'abord, tout le code

python


# coding: utf-8

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, execute
from qiskit.aqua.utils import tensorproduct
from qiskit import BasicAer
from qiskit.quantum_info.analysis import average_data

from scipy.optimize import minimize
import numpy as np
import time


def classical_minimize(cost_func, initial_params, options, method='powell'):
    print('classical minimize is starting now... ')
    start_time = time.time()
    result = minimize(cost_func, initial_params, options=options, method=method)
    print('running time: {}'.format(time.time() - start_time))
    print('opt_cost: {}'.format(result.fun))
    print('opt_params: {}'.format(result.x))
    return result.x


class MAXCUT:

    #Réglage de la valeur initiale
    def __init__(self, n_qubits, weight_matrix, p=1, num_steps=1):
        self.n_qubits = n_qubits
        self.weight_matrix = weight_matrix
        self.P = p
        self.num_steps = num_steps
        self.edge_list = []
        self._make_edge_list()

    #Création d'une liste d'arêtes à partir d'une matrice de poids
    def _make_edge_list(self):
        for i in range(self.weight_matrix.shape[0]):
            for j in range(i+1, self.weight_matrix.shape[1]):
                if self.weight_matrix[i][j] != 0:
                    self.edge_list.append([i, j])

    '------------------------------------------------------------------------------------------------------------------'

    def Zi_Zj(self, q1, q2):
        I_mat = np.array([[1, 0], [0, 1]])
        Z_mat = np.array([[1, 0], [0, -1]])
        if q1 == 0 or q2 == 0:
            tensor = Z_mat
        else:
            tensor = I_mat
        for i in range(1, self.n_qubits):
            if i == q1 or i == q2:
                tensor = tensorproduct(tensor, Z_mat)
            else:
                tensor = tensorproduct(tensor, I_mat)
        return tensor

    def observable(self):
        obs = np.zeros((2**self.n_qubits, 2**self.n_qubits))
        for a_edge in self.edge_list:
            q1, q2 = a_edge
            obs = obs + 0.5 * self.Zi_Zj(q1, q2)
        return obs

    '------------------------------------------------------------------------------------------------------------------'

    # U_C(gamma)
    def add_U_C(self, qc, gamma):
        for a_edge in self.edge_list:
            q1, q2 = a_edge
            qc.cx(q1, q2)
            qc.rz(-2**gamma, q2)
            qc.cx(q1, q2)
        return qc

    # U_X(beta)
    def add_U_X(self, qc, beta):
        for i in range(self.n_qubits):
            qc.rx(-2*beta, i)
        return qc

    def QAOA_output_onelayer(self, params, run=False):
        beta, gamma = params
        qr = QuantumRegister(self.n_qubits)
        cr = ClassicalRegister(self.n_qubits)
        qc = QuantumCircuit(qr, cr)
        qc.h(range(self.n_qubits))
        qc = self.add_U_C(qc, gamma)
        qc = self.add_U_X(qc, beta)
        qc.measure(range(self.n_qubits), range(self.n_qubits))
        NUM_SHOTS = 10000
        seed = 1234
        backend = BasicAer.get_backend('qasm_simulator')
        results = execute(qc, backend, shots=NUM_SHOTS, seed_simulator=seed).result()
        counts = results.get_counts(qc)
        expectation = average_data(counts, self.observable())
        return expectation

    '------------------------------------------------------------------------------------------------------------------'

    def minimize(self):
        initial_params = np.array([0.1, 0.1])
        opt_params = classical_minimize(self.QAOA_output_onelayer, initial_params,
                                        options={'maxiter':500}, method='powell')
        return opt_params

    def run(self):
        opt_params = self.minimize()
        beta_opt, gamma_opt = opt_params
        qr = QuantumRegister(self.n_qubits)
        cr = ClassicalRegister(self.n_qubits)
        qc = QuantumCircuit(qr, cr)
        qc.h(range(self.n_qubits))
        qc = self.add_U_C(qc, gamma_opt)
        qc = self.add_U_X(qc, beta_opt)
        qc.measure(range(self.n_qubits), range(self.n_qubits))
        NUM_SHOTS = 10000
        seed = 1234
        backend = BasicAer.get_backend('qasm_simulator')
        results = execute(qc, backend, shots=NUM_SHOTS, seed_simulator=seed).result()
        print(results.get_counts())


if __name__ == '__main__':
    weight_matrix = np.array([[0, 1, 0, 1],
                             [1, 0, 1, 0],
                             [0, 1, 0, 1],
                             [1, 0, 1, 0]])
    cut = MAXCUT(4, weight_matrix, p=1)
    cut.run()

Je vais reprendre et expliquer uniquement les fonctions qui m'intéressent.

Création de C (Z)

python


    def Zi_Zj(self, q1, q2):
        I_mat = np.array([[1, 0], [0, 1]])
        Z_mat = np.array([[1, 0], [0, -1]])
        if q1 == 0 or q2 == 0:
            tensor = Z_mat
        else:
            tensor = I_mat
        for i in range(1, self.n_qubits):
            if i == q1 or i == q2:
                tensor = tensorproduct(tensor, Z_mat)
            else:
                tensor = tensorproduct(tensor, I_mat)
        return tensor

    def observable(self):
        obs = np.zeros((2**self.n_qubits, 2**self.n_qubits))
        for a_edge in self.edge_list:
            q1, q2 = a_edge
            obs = obs + 0.5 * self.Zi_Zj(q1, q2)
        return obs

python


<\beta,\gamma|C(Z)|\beta,\gamma>

Le C (Z) requis pour calculer est créé ici. À ce stade, il est nécessaire de calculer le produit tensoriel, mais il peut être calculé avec le produit tensoriel de qiskit.aqua.utils.

Calcul de la valeur attendue

Pour calculer la valeur attendue avec qiskit

python


        results = execute(qc, backend, shots=NUM_SHOTS, seed_simulator=seed).result()
        counts = results.get_counts(qc)
        expectation = average_data(counts, self.observable())

Vous pouvez le faire par la méthode de.

résultat

Le résultat de l'exécution est le suivant.

{'0101': 2578, '1110': 171, '1101': 146, '1001': 793, '1111': 141, '0011': 815, '0111': 122, '0010': 159, '0000': 161, '0100': 170, '0001': 151, '0110': 802, '1000': 160, '1100': 811, '1010': 2682, '1011': 138}

Des valeurs plus élevées, 0101 et 1010, peuvent être récupérées sous forme de solutions.

Recommended Posts

Qiskit: Implémentation de QAOA sans Qiskit Aqua
Qiskit: Implémentation de Quantum Boltsman Machine
Qiskit: Implémentation des états d'hypergraphes quantiques
Qiskit: mise en œuvre de l'apprentissage des circuits quantiques (QCL)
Implémentation de la séquence de Fibonacci
Implémentation de VGG16 à l'aide de Keras créé sans utiliser de modèle entraîné
Implémentation informatique quantique de Quantum Walk 2
Implémentation de TF-IDF à l'aide de gensim
Implémentation de MathJax sur Sphinx
Explication et mise en œuvre de SocialFoceModel
Mise en œuvre de la théorie des jeux - Le dilemme du prisonnier -
Mise en œuvre d'une analyse de composants indépendante
Implémentation informatique quantique de Quantum Walk 3
Implémentation Python du filtre à particules
Implémentation du tri rapide en Python
Implémentation informatique quantique de Quantum Walk 1
Apprentissage par renforcement profond 2 Mise en œuvre de l'apprentissage par renforcement
Implémentation de Scale-Space pour SIFT
Explication mathématique de la recherche de dichotomie et de trisection et méthode de mise en œuvre sans bogues