Is qml.AmplitudeEmbedding() supported for IBM HW?

I continue to try different aspects of PennyLane. In this tutorial

you are using amplitude embedding: qml.AmplitudeEmbedding() to input 8x8 images on 6 qubits.
Is an implementation available for this method of state initialization on gate-based real hardware? If not, are there any alternatives for O(100) pixel image embedding for real HW execution when using PennyLane?

I made a simple example which runs on ‘default.qubit’ but crashes in transpiler if I change device to ‘ibmq_qasm_simulator’. The error is:
TranspilerError: "HighLevelSynthesis was unable to synthesize Instruction(name='reset', num_qubits=1, num_clbits=0, params=[ ])."

This is the reproducer:

num_wires = 4
X=np.random.rand(2 ** num_wires)  
if 1:
    from qiskit_ibm_provider import IBMProvider
    provider = IBMProvider()
    backend = provider.get_backend(backN)
    dev = qml.device('qiskit.ibmq', wires=num_wires, backend=backend, shots=2000)
    dev = qml.device('default.qubit', wires=num_wires)

def encoder( features):
    wires = list(range(num_wires))
    qml.AmplitudeEmbedding(features=features, wires=wires, pad_with=0.5)
    return qml.probs(wires=wires)

qnode = qml.QNode(encoder, dev)
# run circuit on IBM HW
probTens = qnode(X)

This is my software stack:

Name: PennyLane
Version: 0.34.0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
License: Apache License 2.0
Location: /usr/local/lib/python3.10/dist-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml, typing-extensions
Required-by: PennyLane-Cirq, PennyLane-Lightning, PennyLane-Lightning-GPU, PennyLane-qiskit, PennyLane-SF

Platform info:           Linux-6.6.9-200.fc39.x86_64-x86_64-with-glibc2.35
Python version:          3.10.12
Numpy version:           1.23.5
Scipy version:           1.11.4
Installed devices:
- default.gaussian (PennyLane-0.34.0)
- default.mixed (PennyLane-0.34.0)
- default.qubit (PennyLane-0.34.0)
- default.qubit.autograd (PennyLane-0.34.0)
- default.qubit.jax (PennyLane-0.34.0)
- default.qubit.legacy (PennyLane-0.34.0)
- (PennyLane-0.34.0)
- default.qubit.torch (PennyLane-0.34.0)
- default.qutrit (PennyLane-0.34.0)
- null.qubit (PennyLane-0.34.0)
- cirq.mixedsimulator (PennyLane-Cirq-0.34.0)
- cirq.pasqal (PennyLane-Cirq-0.34.0)
- cirq.qsim (PennyLane-Cirq-0.34.0)
- cirq.qsimh (PennyLane-Cirq-0.34.0)
- cirq.simulator (PennyLane-Cirq-0.34.0)
- lightning.qubit (PennyLane-Lightning-0.34.0)
- lightning.gpu (PennyLane-Lightning-GPU-0.34.0)
- strawberryfields.fock (PennyLane-SF-0.29.0)
- strawberryfields.gaussian (PennyLane-SF-0.29.0)
- strawberryfields.gbs (PennyLane-SF-0.29.0)
- strawberryfields.remote (PennyLane-SF-0.29.0)
- (PennyLane-SF-0.29.0)
- qiskit.aer (PennyLane-qiskit-0.34.0)
- qiskit.basicaer (PennyLane-qiskit-0.34.0)
- qiskit.ibmq (PennyLane-qiskit-0.34.0)
- qiskit.ibmq.circuit_runner (PennyLane-qiskit-0.34.0)
- qiskit.ibmq.sampler (PennyLane-qiskit-0.34.0)
- qiskit.remote (PennyLane-qiskit-0.34.0)

Hey @Jan_Balewski, thanks for continuing to try PennyLane out!

I’ll have to get back to you on this one :thinking:. Sit tight while I ask around!

Hi @Jan_Balewski, it seems that you have uncovered a bug in Qiskit. The best option is for you to open a bug report in Qiskit directly, but if you don’t know how to do it I can open the report there myself!

What’s happening is that the conversion of AmplitudeEmbedding to instructions for Qiskit requires the use of the QuantumCircuit.reset Qiskit function. It’s the same bug reported here for the Aer simulator (looks to be fixed in qiskit_aer 0.13.1), but it seems like the bug is still there in the QASM simulator. This code is being called on the Qiskit end and failing:

from qiskit_ibm_provider import IBMProvider
from qiskit import QuantumRegister, QuantumCircuit, transpile

provider = IBMProvider()
backend = provider.get_backend("ibmq_qasm_simulator")

qr= QuantumRegister(2)
qc = QuantumCircuit(qr)

transpiled_qc = transpile(qc, backend)

Because they have already fixed this bug in the Aer simulator, there is a bit of a work-around you can use here to get your code above to run - you can use one backend to compile and another to run.

To do this, make sure you have qiskit_aer 0.13.1 or higher installed in your environment (otherwise you can pip install), and then add a QiskitAer device as the compilation backend when initializing your device in PennyLane. Then it will use the Aer simulator for the transpile function that is failing above, and the transpiled circuit will run on the QASM simulator. You do this by adding the compile_backend kwarg to device and passing it an instance of AerSimulator - everything else in your code can stay the same.

I.e. where you create the device, use

from qiskit_aer import AerSimulator

dev = qml.device('qiskit.ibmq', 

I do notice that you mention in your text running on hardware. I tried switching out the simulator in your code with the ibm_kyoto device, that that successfully compiled and queued a task for the hardware to run. It will be a few hours until I can see the results of that, but at the moment it looks like your code should compile fine if/when you want to move from the QASM simulator backend to a hardware backend!

If you have other questions, or need help opening a bug report with Qiskit, let me know!

Thank you Lillian for your help. I’m home now.

I just tested Aer and I get the correct results, within statistical error, e.g. for 1000 shots and 16 pixels image stored on 4 qubits gives me

num_wires = 4
X=np.random.rand(2 ** num_wires)
probTens = qnode(X) 
print('Max error in prob=%.3f'%maxErr)

Results with: Max error in prob=0.027

Also, I’m able to run the same circuit against real HW: ‘ibm_cairo’, ‘ibm_hanoi’ and get some results. The error is much larger but due to limited connectivity the circuit depth is approaching 30 CX-gates I do no corrections. That is life.
Thanks again

It’s great that you could solve this with Lillian’s help @Jan_Balewski !

Enjoy using PennyLane!