Dieses Mal werden wir VQE (Variational Quantum Eigen Solver) unter Verwendung des Open Source Frameworks für Quantencomputer implementieren, das von IBM bereitgestellt wird. Es wird erwartet, dass dieser Algorithmus auf die Quantenchemie angewendet wird. Eine theoretische Erklärung finden Sie unter Quantum Native Dojo. Ich denke, es gibt mehrere VQE-Implementierungsartikel, aber die meisten japanischen Artikel wurden mit Qulacs und Blueqat geschrieben, deshalb habe ich diesmal versucht, sie mit Qiskit zu implementieren. Ich habe in der Vergangenheit Artikel über QAOA und QCL geschrieben. Implementierung von QAOA ohne Qiskit Aqua Implementierung von Quantum Circuit Learning
Bibliotheksimport
python
from qiskit import Aer, execute
from qiskit import QuantumCircuit
from qiskit.aqua.utils import tensorproduct
from qiskit.quantum_info.analysis import average_data
from scipy.optimize import minimize
import numpy as np
Initialisieren
python
class VQE:
def __init__(self, n_qubits, observable, layer, backend):
self.n_qubits = n_qubits
self.OBS = observable
self.Layer = layer
self.backend = backend
Dieses Mal wird Hamiltonian auch als Eingabe behandelt.
Schaltung erstellen
python
def make_circuit(self, Params):
def make_U_circuit(circ, params):
for n in range(self.n_qubits):
param = params[3*n:3*(n+1)]
circ.rz(param[0], n)
circ.rx(param[1], n)
circ.rz(param[2], n)
return circ
def make_Ent(circ):
for n in range(self.n_qubits-1):
circ.cx(n, n+1)
return circ
#Richten Sie die Schaltung ein
circ = QuantumCircuit(self.n_qubits, self.n_qubits)
for l in range(self.Layer):
#Erstellen einer Parameterschaltung
params = Params[3*self.n_qubits*l:3*self.n_qubits*(l+1)]
#Eine Verschränkung schaffen
make_U_circuit(circ, params)
#Anzahl der Schichten-Weil es 1 sein muss
if l != self.Layer-1:
make_Ent(circ)
#Messung
circ.measure(circ.qregs[0], circ.cregs[0])
return circ
VQE-Ausführungsphase
python
def outputlayer(self, params):
circ = self.make_circuit(params)
counts = execute(circ, backend=self.backend, shots=8192).result().get_counts()
return average_data(counts, self.OBS)
def initial_params(self):
#Anfangsparameter erstellen
init = [0.1 for _ in range(3 * self.Layer * self.n_qubits)]
return np.array(init)
def minimize(self):
initial_params = self.initial_params()
#Führen Sie eine Optimierung durch
opt_params, opt_cost = classica_minimize(self.outputlayer, initial_params, options={'maxiter':500})
circ = self.make_circuit(opt_params)
counts = execute(circ, backend=self.backend, shots=8192).result().get_counts()
ans = sorted(counts.items(), key=lambda x: x[1], reverse=True)
print(ans)
return opt_cost
Außerdem wird im Gegensatz zu anderen Artikeln eine Schicht verwendet. Dies ist in Referenz [1]. Ich werde es kurz erklären. Wenn $ \ theta = (\ theta_1, \ theta_2, \ cdots, \ theta_d) $ ein Satz von Parametern ist, ist die Schaltung
python
U(\theta) = U_d(\theta_d)U_{ENT} \cdots U_1(\theta_1)U_{ENT}U_0(\theta_0)
Kann geschrieben werden. Zu diesem Zeitpunkt ist $ d $ die Anzahl der Ebenen. Durch Setzen von $ d = 2 $ ist es möglich, dieselbe Schaltung wie andere Artikel zu erstellen.
Dieses Mal werde ich die Formel verwenden, die auch in anderen Artikeln als Hamiltonian behandelt wird. Supplementary Information
python
def sample_hamiltonian():
'''
https://dojo.qulacs.org/ja/latest/notebooks/5.1_variational_quantum_eigensolver.html
Hamiltonian wird verwendet.
'''
I_mat = np.array([[1, 0], [0, 1]])
X_mat = np.array([[0, 1], [1, 0]])
Z_mat = np.array([[1, 0], [0, -1]])
obs = np.zeros((4, 4))
obs += -3.8505 * tensorproduct(I_mat, I_mat)
obs += -0.2288 * tensorproduct(I_mat, X_mat)
obs += -1.0466 * tensorproduct(I_mat, Z_mat)
obs += 0.2613 * tensorproduct(X_mat, X_mat)
obs += 0.2288 * tensorproduct(X_mat, Z_mat)
obs += -1.0466 * tensorproduct(Z_mat, I_mat)
obs += 0.2288 * tensorproduct(Z_mat, X_mat)
obs += 0.2356 * tensorproduct(Z_mat, Z_mat)
return obs / 2
Ich benutze auch die Funktionen, die ich in anderen Artikeln verwende, die ich für die klassische Optimierung schreibe.
python
def classica_minimize(cost_func, initial_params, options, method='powell'):
print('classical minimize is starting now... ')
result = minimize(cost_func, initial_params, options=options, method=method)
print('opt_cost: {}'.format(result.fun))
print('opt_params: {}'.format(result.x))
return result.x, result.fun
Es ist Ausführung.
python
if __name__ == '__main__':
backend = Aer.get_backend('qasm_simulator')
obs = sample_hamiltonian()
vqe = VQE(2, obs, 2, backend)
vqe.minimize()
-2.85405 #vqe Ergebnis
-2.8626207640766816 #Minimaler Eigenwert
Im Vergleich zu anderen Artikeln ist die Genauigkeit geringer, aber ist es ein Erfolg ...?
Ich habe versucht, VQE mit Qiskit zu implementieren. Um ehrlich zu sein, bevorzuge ich QAOA, das für klassische Probleme geeignet ist, gegenüber VQE. Deshalb habe ich diesen Artikel zum Zweck der vollständigen Implementierung geschrieben. Bitte machen Sie Ihre eigene Theorie ...
[1] Hardware-efficient variational quantum eigensolver for small molecules and quantum magnets [2] Quantum Native Dojo
Recommended Posts