# Creating a custom VariationalForm in Qiskit

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 floats. 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.)

• I see, no there is currently no way to not use the Parameter class. That used to be possible but was removed because there was no use-case where Parameter 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. – Cryoris May 27 '20 at 16:41

You can plug any parameterized QuantumCircuit into the VQE. Parameterized means it contains Parameter objects e.g. as rotation angles. For instance

from qiskit.circuit import QuantumCircuit, ParameterVector
from qiskit.aqua.algorithms import VQE

params = ParameterVector(3)
wavefunction = QuantumCircuit(3)
wavefunction.ry(params[0], 0)
wavefunction.ry(params[1], 1)
wavefunction.ry(params[2], 2)

vqe = VQE(var_form=wavefunction, ...)


I'd suggest you to have a look at the circuit library, especially the N-local circuits as e.g. the TwoLocal circuit.

This notebook explains this in more detail and shows some of the new functionality of Qiskit 0.19.0 concerning the circuit library and how it interacts with Aqua.

• Thanks! Looks like it was the ParameterVector thing which I was unaware of, and which works as a simple solution. – mavzolej May 18 '20 at 20:32
• Could you please suggest a solution not relying on Parameter objects? I would like to use a 'black box' function which takes as input some numbers and returns a QuantumCircuit object. – mavzolej May 19 '20 at 1:43
• I also have the following solution: instead of using the built-in Qiskit VQE() function, I could simply use scipy minimize, if I manage to write a function which would calculate the expectation value of a given operator in a given state. How do I do this in Qiskit? – mavzolej May 19 '20 at 3:55
• Did you have a look at the notebook? There the TwoLocal object is presented which takes input parameters and returns a QuantumCircuit. Is that what you're looking for? About computing the expectation value: That turns into another topic, maybe you could open another question for this? I'm sure more people are interested in this! – Cryoris May 19 '20 at 8:15
• Thanks, asked here. As for TwoLocal: it seems like it's only capable of implementing circuits of specific forms. While I wanted var_form to generate arbitrary gate sets depending on the parameters provided as floats, potentially using some external libraries (which are unaware of the Parameter class). – mavzolej May 19 '20 at 12:18

You basically have to construct:

1. A parametrized circuit
2. Objective function which returns the cost
3. Minimize the cost with the classical optimizer eg. COBYLA

I haven't tried, but probably you can create your own type which extends ParameterExpression type(class) and define your custom function (in this case sqrt) so that it can be applied on the Parameter obj during the training/testing phase. Paramter objects can only evaluate basic arithmetic operations, which probably you might have already observed.

May be I will try and let you know if it works. But looks possible.

• I ended up creating my own parameterized function, inside which I'm calculating expectation values, and sending it to scipy.minimize. IMHO Qiskit's VQE function is too much tied to quantum chemistry and doesn't provide enough flexibility to work with general fermionic systems. – mavzolej Sep 19 '20 at 1:29