[PYTHON] Qiskit: Implementierung von QAOA ohne Qiskit Aqua

Einführung

In meinem ersten Artikel habe ich Ich habe versucht, TSP mit QAOA zu lösen veröffentlicht. Hierbei wurde jedoch eine sogenannte modularisierte Version von qiskit aqua verwendet, was möglich ist, ohne dass die Schaltung selbst entworfen werden muss. Dieses Mal möchte ich QAOA ohne Qiskit Aqua verwenden. Verwenden Sie zuerst den maximalen Schnitt als ersten Schritt. Um ehrlich zu sein, denke ich, dass andere Probleme nur durch Ändern des Hamilton-Operators gelöst werden können. Ich hoffe, dass dies eine Referenz für diejenigen ist, die Quantenprogrammierung mit Qiskit durchführen. Es gibt mehrere Websites, die die Quantenprogrammierung auf Japanisch erklären, aber da alle unterschiedliche Quantenprogrammiersprachen verwenden, halte ich meinen in qiskit geschriebenen Artikel auch für sinnvoll.

Auch in diesem Artikel möchte ich den Code von Qiskit erläutern, vorausgesetzt, dass die Erklärung von QAOA selbst anderen Personen überlassen bleibt.

Referenz: Quantum Native Dojo

code

Zunächst der gesamte 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:

    #Anfangswerteinstellung
    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()

    #Erstellen einer Kantenliste aus der Gewichtsmatrix
    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()

Ich werde nur die Funktionen aufgreifen und erklären, die mich interessieren.

Erstellen von 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>

Hier wird das zur Berechnung erforderliche C (Z) erstellt. Zu diesem Zeitpunkt ist es notwendig, das Tensorprodukt zu berechnen, es kann jedoch mit dem Tensorprodukt von qiskit.aqua.utils berechnet werden.

Berechnung des erwarteten Wertes

Berechnung des erwarteten Wertes mit qiskit

python


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

Sie können es nach der Methode von tun.

Ergebnis

Das Ausführungsergebnis ist wie folgt.

{'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}

Größere Werte, 0101 und 1010, können als Lösungen abgerufen werden.

Recommended Posts

Qiskit: Implementierung von QAOA ohne Qiskit Aqua
Qiskit: Implementierung einer Quantenbolzenmaschine
Qiskit: Implementierung von Quantenhypergraphzuständen
Qiskit: Implementierung von Quantum Circuit Learning (QCL)
Implementierung der Fibonacci-Sequenz
Implementierung von VGG16 mit Keras, die ohne Verwendung eines trainierten Modells erstellt wurden
Quantum Computer Implementierung von Quantum Walk 2
Implementierung von TF-IDF mit Gensim
Implementierung von MathJax auf Sphinx
Erklärung und Implementierung von SocialFoceModel
Implementierung der Spieltheorie - Gefangenendilemma -
Implementierung einer unabhängigen Komponentenanalyse
Quantum Computer Implementierung von Quantum Walk 3
Python-Implementierung des Partikelfilters
Implementierung der schnellen Sortierung in Python
Quantum Computer Implementierung von Quantum Walk 1
Tiefes Lernen der Verstärkung 2 Implementierung des Lernens der Verstärkung
Implementierung von Scale-Space für SIFT
Mathematische Erklärung der Dichotomie- und Trisektionssuch- und Implementierungsmethode ohne Fehler