This time, we will implement VQE (Variational Quantum Eigen solver) using the open source framework for quantum computers provided by IBM. This algorithm is expected to be applied to quantum chemistry. Please refer to Quantum Native Dojo for a theoretical explanation. I think there are multiple VQE implementation articles, but most of the Japanese articles are written using Qulacs and Blueqat, so I tried to implement them with Qiskit this time. I have written articles on QAOA and QCL in the past, so please take a look. Implementation of QAOA without Qiskit Aqua Implementation of Quantum Circuit Learning
Library import
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
Initialize
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
This time, Hamiltonian is also treated as input.
Creating a 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
#Set up the circuit
circ = QuantumCircuit(self.n_qubits, self.n_qubits)
for l in range(self.Layer):
#Creating a parameter circuit
params = Params[3*self.n_qubits*l:3*self.n_qubits*(l+1)]
#Creating entanglement
make_U_circuit(circ, params)
#Number of layers-Because it has to be 1
if l != self.Layer-1:
make_Ent(circ)
#Measurement
circ.measure(circ.qregs[0], circ.cregs[0])
return circ
VQE execution phase
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):
#Creating initial parameters
init = [0.1 for _ in range(3 * self.Layer * self.n_qubits)]
return np.array(init)
def minimize(self):
initial_params = self.initial_params()
#Perform optimization
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
In addition, unlike other articles, layer is used. This is in reference [1]. I will explain briefly. When $ \ theta = (\ theta_1, \ theta_2, \ cdots, \ theta_d) $ is a set of parameters, the circuit
python
U(\theta) = U_d(\theta_d)U_{ENT} \cdots U_1(\theta_1)U_{ENT}U_0(\theta_0)
Can be written. At this time, $ d $ is the number of layers. By setting $ d = 2 $, it is possible to create the same circuit as other articles.
This time, I will use the formula that Hamiltonian deals with in other articles. Supplementary Information
python
def sample_hamiltonian():
'''
https://dojo.qulacs.org/ja/latest/notebooks/5.1_variational_quantum_eigensolver.html
Hamiltonian is used.
'''
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
I also use the functions I use in other articles I write for classical optimization.
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
It is execution.
python
if __name__ == '__main__':
backend = Aer.get_backend('qasm_simulator')
obs = sample_hamiltonian()
vqe = VQE(2, obs, 2, backend)
vqe.minimize()
-2.85405 #vqe result
-2.8626207640766816 #Minimum eigenvalue
Compared to other articles, the accuracy is lower, but is it a success ...?
I implemented VQE using Qiskit. To be honest, I prefer QAOA, which is suitable for classical problems, to VQE, so I wrote this article for the purpose of complete implementation. Please do your own theory ...
[1] Hardware-efficient variational quantum eigensolver for small molecules and quantum magnets [2] Quantum Native Dojo
Recommended Posts