Cette fois, nous allons implémenter VQE (Variational Quantum Eigen Solver) en utilisant le framework open source pour les ordinateurs quantiques fourni par IBM. Cet algorithme devrait être appliqué à la chimie quantique. Veuillez consulter Quantum Native Dojo pour une explication théorique. Je pense qu'il existe plusieurs articles d'implémentation VQE, mais la plupart des articles japonais sont écrits en utilisant Qulacs et Blueqat, j'ai donc essayé de les implémenter avec Qiskit cette fois. J'ai écrit des articles sur QAOA et QCL dans le passé, alors jetez un œil. Implémentation de QAOA sans Qiskit Aqua Mise en œuvre de l'apprentissage des circuits quantiques
Importation de bibliothèque
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
Initialiser
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
Cette fois, l'hamiltonien est également traité comme une entrée.
Créer un circuit
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
#Mettre en place le circuit
circ = QuantumCircuit(self.n_qubits, self.n_qubits)
for l in range(self.Layer):
#Créer un circuit de paramètres
params = Params[3*self.n_qubits*l:3*self.n_qubits*(l+1)]
#Créer un enchevêtrement
make_U_circuit(circ, params)
#Nombre de couches-Parce que ça doit être 1
if l != self.Layer-1:
make_Ent(circ)
#La mesure
circ.measure(circ.qregs[0], circ.cregs[0])
return circ
Phase d'exécution VQE
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):
#Création des paramètres initiaux
init = [0.1 for _ in range(3 * self.Layer * self.n_qubits)]
return np.array(init)
def minimize(self):
initial_params = self.initial_params()
#Effectuer l'optimisation
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
De plus, contrairement à d'autres articles, une couche est utilisée. C'est dans la référence [1]. Je vais vous expliquer brièvement. Lorsque $ \ theta = (\ theta_1, \ theta_2, \ cdots, \ theta_d) $ est un ensemble de paramètres, le circuit
python
U(\theta) = U_d(\theta_d)U_{ENT} \cdots U_1(\theta_1)U_{ENT}U_0(\theta_0)
Peut être écrit. À ce stade, $ d $ est le nombre de couches. En mettant $ d = 2 $, il est possible de créer le même circuit que les autres articles.
Cette fois, j'utiliserai la formule qui est également traitée dans d'autres articles comme hamiltonien. Supplementary Information
python
def sample_hamiltonian():
'''
https://dojo.qulacs.org/ja/latest/notebooks/5.1_variational_quantum_eigensolver.html
Hamiltonian est utilisé.
'''
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
J'utilise également les fonctions que j'utilise dans d'autres articles que j'écris pour l'optimisation classique.
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
C'est l'exécution.
python
if __name__ == '__main__':
backend = Aer.get_backend('qasm_simulator')
obs = sample_hamiltonian()
vqe = VQE(2, obs, 2, backend)
vqe.minimize()
-2.85405 #résultat vqe
-2.8626207640766816 #Valeur propre minimale
Par rapport à d'autres articles, la précision est moindre, mais est-ce un succès ...?
J'ai essayé d'implémenter VQE en utilisant Qiskit. Pour être honnête, je préfère QAOA, qui convient aux problèmes classiques, à VQE, j'ai donc écrit cet article dans le but d'une implémentation complète. Veuillez faire votre propre théorie ...
[1] Hardware-efficient variational quantum eigensolver for small molecules and quantum magnets [2] Quantum Native Dojo
Recommended Posts