I would like to use the built-in Qiskit VQE()
function, with my own variational form. What is the proper way to define it? I was expecting var_form
to be simply a function returning an object of type QuantumCircuit
for a particular set of parameters (that's how it's done in Pyquil).
More precisely: how do I manually create an instance of the VariationalForm
class which would correspond to preparing the desired program for a given set of parameters?
So far my understanding is that I have to do smth like that:
class my_var_form(VariationalForm):
def construct_circuit(self,
parameters: Union[List[float], np.ndarray],
q: Optional[QuantumRegister] = None) -> NoReturn:
circuit = QuantumCircuit(q)
...
return circuit
Is this the proper way to do things?
CLARIFICATION
Let us define a function which would generate a Qiskit circuit for an arbitrary parameter of type float
:
def black_box( param : float ):
qc = qskt.QuantumCircuit( 1 )
qc.u1( np.sqrt( param ), 0 )
return qc
np.sqrt()
was chosen as a toy example, one could equally well replace it with any fucntion defined on float
s. To make sure that the function makes sense, one can do this:
job = execute( black_box( 1. ), get_backend('qasm_simulator') ) # Works fine
Now, let us try to define a VariationalForm
which will use our black_box
function:
class my_var_form( VariationalForm ):
def __init__(self, numpar, numq, bnds) -> None:
super().__init__()
self._num_parameters = numpar
self._num_qubits = numq
self._bounds = bnds
pass
def construct_circuit(self,
parameters: Union[List[float], np.ndarray],
q: Optional[qskt.QuantumRegister] = None) -> NoReturn:
circuit = black_box( parameters[0] )
return circuit
However, the following code fails to work:
var_form_instance = my_var_form( 1, 1, [[-2., 2]] )
vqe = VQE( WeightedPauliOperator( [1., Pauli([0.],[0.])] ),
var_form_instance,
L_BFGS_B(),
np.array([0])
)
With the following error:
TypeError: loop of ufunc does not support argument 0 of type Parameter which has no callable sqrt method
The problem is that Qiskit no matter what wants to use its built-in Parameter
class which is based on the sympy
package.
How can I overcome this issue? Or is there absolutely no way I could use the built-in VQE
function without dealing with Parameter
class?
My question arises from the fact that I use an external library to generate circuits which I then convert to Qiskit format. Thus, I have a function which returns a Qiskit circuit for a set of real parameters. I would like the Qiskit VQE()
function to use my own black_box()
function for generating the quantum circuit on each step of the minimization.
(Alternatively, I could just not use VQE()
at all, and simply run the classical minimizer myself, only using Qiskit for evaluating the expectation value of the Hamiltonian on each step... but apparently there's no built-in function for calculating the expectation value neither of a Pauli string, nor even of individual Pauli operators! See my question here: to my understanding SnapshotExpectationValue()
is an unphysical method, and does not allow one to calculate expectation values of Pauli strings using sampling on real devices.)
Parameter
class. That used to be possible but was removed because there was no use-case whereParameter
did not work. You open an issue on GitHub to address this :) However there are ways to calculate expectation values, its actually quite easy. Check out this notebook. $\endgroup$