Qiskit / qiskit-tutorials

A collection of Jupyter notebooks showing how to use the Qiskit SDK
Apache License 2.0
2.31k stars 1.29k forks source link

Problem regarding variation quantum eigensolver #515

Closed OChiB closed 5 years ago

OChiB commented 5 years ago

Informations

I want to program my own variation quantum eigensolver for my own practice. The Hamiltonian considering is a two level system, so Pauli-z gate. The ansatz state is rotated by the ry gate. The problem is, the program works fine, if I use the defined function once, which returns the measurement result for a certain parameter angle. For example, if I set the angle to pi, it returns -1.0 as expected. But, it fails, if I use this function iteratively, for example, by making use of for-loop. In this case, the measurement result converges to 0, but not to -1.

What I think is, the classical register does not initialize the measurement result, if I use it repeatedly. How can I fix it?

Thank you very much in advance!

This is my code:

#Testing variational quantum eigensolver

from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit import available_backends, execute, register, get_backend
from qiskit.tools.visualization import circuit_drawer
from qiskit.tools.qi.qi import state_fidelity
from qiskit import Aer

backend = Aer.get_backend('qasm_simulator')

#additional packages
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import minimize
import math

#define Quantum register: 1 qubit
qreg = QuantumRegister(1)
creg= ClassicalRegister(1)
#define quantum circuit for 1 qubit
qc = QuantumCircuit(qreg, creg)

#define expectation value of H
def expec(theta):
    #define number of samples/measurements
    samples = 10000

    #ansatz state
    qc.ry(float(theta[0]),qreg[0])

    #measurement (sampling)
    qc.measure(qreg[0], creg[0])

    backend = Aer.get_backend('qasm_simulator')

    job = execute(qc,backend,shots=samples)
    result = job.result()

    #calculate expectation
    c0 = result.get_counts(qc).get('0',0)/samples
    c1= result.get_counts(qc).get('1',0)/samples

    print(c0 - c1)
    return c0 - c1
    #store result

#single test
"""
test = expec([np.pi])
print(test)
"""

#iterative test
"""
for k in range(10):
    test = expec([2*np.pi*(k-5)/10])
    print(test)
"""
#iterative test with plot
"""
params_range = np.linspace(0.0, 2 * np.pi, 25)
data = [expec([angle]) for angle in params_range]

plt.xlabel('Parameter value')
plt.ylabel('Expectation value')
plt.plot(params_range, data)
plt.show()
"""

#minimization algorithm using Nelder-Mead Simplex Method
"""
theta_init = [2.0]
minimum = minimize(expec,theta_init, method ='Nelder-Mead',options= {'maxiter':10, 'initial_simplex': np.array([[0.0], [0.05]]),'fatol': 1.0e-1})

print(minimum.x)
"""
chunfuchen commented 5 years ago

@OChiB do you mind reformat your script? you can use "```python ```" to wrapper your script.

I guess that there is something wrong in the calculation of your expection, it should be c1 - c0.

On the other hand, Aqua provides APIs to build VQE. Here is the equvelent script as yours. and I do get the result is -1.

from qiskit import Aer
from qiskit.quantum_info import Pauli
from qiskit_aqua import Operator, set_aqua_logging
from qiskit_aqua.algorithms import VQE
from qiskit_aqua.components.variational_forms import RY
from qiskit_aqua.components.optimizers import NELDER_MEAD
import logging

# set to INFO to see the evaluation progress
set_aqua_logging(logging.INFO)

# prepare qubit operator
H = Operator(paulis=[[1.0, Pauli.from_label('Z')]])

# get backend
backend = Aer.get_backend('qasm_simulator')

# setup VQE
var_form = RY(H.num_qubits, depth=1)
optimizer = NELDER_MEAD(maxfev=100)
algo = VQE(H, var_form, optimizer, 'paulis')

# run it
result = algo.run(backend, shots=8192)
print(result['eigvals'][0])
OChiB commented 5 years ago

@chunfuchen Thank you for your reply! Regarding to the expectation calculation. It shouldn't be wrong, since this expectation value return -1 for the angle pi. And I think this is not the main issue, since the essential problem lies on the iterative algorithm, not in the calculation of the expectation value itself (since otherwise the expectation value should give 1 or -1, but not 0).

I tried to run your code, but I get

TypeError: '>=' not supported between instances of 'QuantumRegister' and 'int'

I have updated the qiskit, qiskit-aqua, and qiskit-chemistry, but this also doesn't work.

chunfuchen commented 5 years ago

@OChiB I am using qiskit 0.7.2, do you mind upgrading your qiskit to the newest version?

here is my env

qiskit                                 0.7.2
qiskit-aer                             0.1.1
qiskit-aqua                            0.4.1   
qiskit-chemistry                       0.4.2
qiskit-terra                           0.7.0
chunfuchen commented 5 years ago

@OChiB I found a bug in your code, you should move the declaration of QuantumCircuit into your def expec(theta) function otherwise, the qc is a reference, which means you keep appending the ry gate.

After I move the declaration of QuantumCircuit into your def expec(theta) function, it converges to -1

OChiB commented 5 years ago

@chunfuchen Oh thank you very much !! I could fix it!!