Pennylane-qiskit IBMQ does not allow for batching circuits?

I’m experimenting with variational classifier which I have trained and obtained the optimal parameters. I wanted to score my trained model on the IBMQ cloud service, the following code contains the predict function for a set of data:


def predict(X,y,params):
    predicted_labels = [np.sign(variational_classifier(params, x=x)) for x in X]
    return predicted_labels, accuracy(y,predicted_labels)

I’ve already experimented with the IBMQ experience on qiskit and you can send a list of compiled circuits to the cloud as usually the quantum processors would be able to take up to 75 experiments at once in a single job submission. Can I work with batched circuits modifying my code or am I constrained to score a single example for a IBMQ job?

Thanks you very much!

Hi @RicardoGaGu,

If I understand correctly, you would like to submit a batch of independent jobs to IBMQ as a single batch?

Unfortunately this is not yet supported by the PennyLane-qiskit plugin, but thanks for bringing it to our attention! This is definitely a feature we would like to support.

2 Likes

Hi @josh,

Just wanted to check if there was any new development on this batching issue.

Thank you!

Hi @tfelefly! This should now be supported using the latest versions of the Qiskit plugin and PennyLane :slight_smile:

1 Like

@josh Could you point me documentation for how this functionality can be used? Is it just with dev.batch_execute()? If yes, instead of running qnodes I would assume that the user will have to construct QuantumTape objects, a list of which can be passed to dev.batch_execute?

Hey @mudit2812!

Once a device supports dev.batch_execute, there are two ways to utilize this functionality:

  • Using QNodes: Any batch_transform that is applied to the QNode (such as the parameter-shift rule, Hamiltonian expansion) will lead to multiple tapes under the hood. These will all be passed as a single batch of tapes to the device.

  • Using Tapes: You can make use of the qml.execute function to directly execute a batch of tapes on a device.

Unfortunately, there is no UI yet for manually specifying multiple circuits to execute in batch at the QNode level.

Hi @mudit2812 and @josh.
Sorry to jump into this discussion, but I have a question related to this.
I have a trained VQC algorithm (AngleEmbedding+StronglyEntanglingLayers), and I want to evaluate this circuit on several different “events” (therefore different inputs) on a real IBM device (with a 300 jobs threshold per execution).
Does this qml.execute work for this case? Is there a minimal working example for the IBM application?

Thanks :smiley:

Hi @Davide_Zuliani,

We now support parameter broadcasting so maybe you can do something like the following:

import pennylane as qml
from pennylane import numpy as np

n_wires = 4

# Set up your device
b = "ibmq_quito"
dev = qml.device(
    "qiskit.ibmq",
    wires=n_wires,
    backend=b,
)

# Create your qnode
@qml.qnode(dev)
def circuit(feature_vector,parameters):
    qml.AngleEmbedding(features=feature_vector, wires=range(n_wires), rotation='Z')
    qml.StronglyEntanglingLayers(weights=parameters, wires=range(n_wires))
    # Return the expectation value on the computational basis for every qubit
    return [qml.expval(qml.PauliZ(i)) for i in range(n_wires)]

# Create your features vector. Here X has 2 sets of 4 features. Parameter broadcasting happens under the hood.
X = np.random.random(size=(2,n_wires),requires_grad=False)

# Create your trainable parameters
shape = qml.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
weights = np.random.random(size=shape,requires_grad=True)


print(qml.draw(circuit, expansion_strategy="device")(X,weights))

print(X)

circuit(X,weights)

Here X are your features and weights are your trainable parameters. Here X has size=(2,n_wires) because you have 2 sets of 4 features.

Please let me know if this helps or if you have any further questions!

@CatalinaAlbornoz does this work when a qnode is transformed into a TorchLayer ?

It seem that by default a TorchLayer is not batching the inputs and submitting a job to the ibmq device for each circuit

Here is a minimal example extending the one from @CatalinaAlbornoz where the circuit is included into a TorchLayer and run.

# %%
import pennylane as qml
from pennylane import numpy as np

# %%
import os 

n_wires = 4

# Set up your device
b = "ibmq_lima"
dev = qml.device(
    "qiskit.ibmq",
    wires=n_wires,
    backend=b,
    ibmqx_token=os.getenv("PYTKET_QA_QISKIT_TOKEN"),
)

# %%
# Create your qnode
@qml.qnode(dev)
def circuit(feature_vector, parameters):
    qml.AngleEmbedding(features=feature_vector, wires=range(n_wires), rotation="Z")
    qml.StronglyEntanglingLayers(weights=parameters, wires=range(n_wires))
    # Return the expectation value on the computational basis for every qubit
    return [qml.expval(qml.PauliZ(i)) for i in range(n_wires)]


# %%
# Create your features vector. Here X has 5 sets of 4 features. Parameter broadcasting happens under the hood.
X = np.random.random(size=(5, n_wires), requires_grad=False)

# Create your trainable parameters
shape = qml.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
weights = np.random.random(size=shape, requires_grad=True)



# %%
import matplotlib.pyplot as plt 
fig, ax = qml.draw_mpl(circuit, expansion_strategy="device")(X, weights)
plt.show()

# %%
circuit(X, weights)

# %%
# Create your qnode
@qml.qnode(dev)
def circuit2(inputs, weights):
    qml.AngleEmbedding(features=inputs, wires=range(n_wires), rotation="Z")
    qml.StronglyEntanglingLayers(weights=weights, wires=range(n_wires))
    # Return the expectation value on the computational basis for every qubit
    return [qml.expval(qml.PauliZ(i)) for i in range(n_wires)]

# %%
sweights = {"weights": shape}
qlayer = qml.qnn.TorchLayer(circuit2, sweights)

# %%
import torch

qlayer(torch.tensor(X))

# %%

The jobs on the IBM Q dashboard show up as 5 circuits in a single job for the circuit(X, weights) call, and as 5 separate jobs of 1 circuit each for the qlayer(torch.tensor(X)) call.

Hi @erinaldiq ,

I see that Tom is helping you in this thread. We can continue the discussion there. Have you been able to solve your issue yet?

Hi,

The solution by Tom worked for single layer but the requirement of “qml.enable_return()” seems to affect things when other layers from pytorch are combined with the qml torch layer.
If you can help, I will share more info about my problem and the error messages. I tried testing a couple of iterations of my code but failed with different errors every time.

Hi @erinaldiq,

I’m sorry to hear that “qml.enable_return()” is causing problems. It would be good if you could mention this and add more details about your problems and error messages in the thread with Tom and Romain so that they’re in the loop too.

I’ll be waiting to see your post in the other thread!

Dear Pennylaners,

I have a variational quantum circuit, which was successfully trained with a ‘lightning.qubit’ device.

Next: With this trained model I want to evaluate the predictions now for all my data on a real quantum backend. In my case, I want to use one of IBM’s as they are currently for free. I first try on their online simulator ‘qasm_simulator’. Submitting jobs is not a problem at all, but I am only able to submit one circuit per job. The problem is also that the next job is only submitted after the first ran through successfully. However, I want for example to send 300 circuits to evaluate at once and not wait again in the queue after each circuit individually.

To fix this read through the docs and found:

  • qnodes
  • qscripts
  • QuantumTape
  • QuantumScript
  • make_qscript
  • QNode_Collection (deprecated)
  • creating tape manually

but unfortunately none of the above worked for me and I observe the same behaviour as described above. I couldn’t find a single example of what one is supposed to do here. My question is whether this is a pennylane-qiskit related problem or if I am missing something here.

Best,
Danya

P.S. The only workaround I found so far is to export the parameters from the trained model from pennylane and import them to an equivalent circuit in qiskit. There I can just pass multiple circuits in job, by giving a list[qc_1, … qc_n], which in pennylane qml.tape.qscript and qml.tape.QuantumTape are supposed to do.

1 Like

Hey @DanyaLearning! Welcome to the forum :rocket:

Can you provide some code that you’re trying to execute and having issues with? That will help us understand your issue better :slight_smile: