Troubles with mapping virtual to physical qubits on a IBM's backend

Hi! A simple question that however is causing me some troubles.
I’m trying to design a personalized schedule for IBM’s backend (real QPU). All the customized settings but one work. Specifically, I was trying to map the virtual qubits to a specific set on the QPU through the initial_layout as written in the qiskit documentation, but Pennylane seems to ignore this.
My Hamiltonian is already mapped into the physical qubits, and clearly an error message returns from Pennylane, warning me that some wires are not found. I insert the initial_layout as a list of qubits into the device() function, but maybe I’m missing something.

Hi @Alex1 ,

Thanks for sharing this here! Could you please share a minimal reproducible code example and the full error traceback so that we can investigate?

IMPORTANT: please don’t share your API key nor any confidential data.

For sure, sorry for the Italian in some parts of the code. I reported the code for the simulator. Another question: theoretically the resilience level is activated in the Pennylane circuit, right? This is the output: neo-ale-pc@Neo-Ale-PC–Aspire-E1-572:~/qenv_jl/Article project/Bonsai Mapping/Ultimate code$ python3 test.py
:white_check_mark: Connection to IBM Quantum ready!
Inserisci dimensioni reticolo (Lx Ly): 3 3
Inserisci parametri del sistema (t U): 0 1

Esecuzione circuito…
Traceback (most recent call last):
File “/home/neo-ale-pc/qenv_jl/Article project/Bonsai Mapping/Ultimate code/test.py”, line 139, in
values = np.array(circuito(0.2))
^^^^^^^^^^^^^
File “/home/neo-ale-pc/qenv_jl/lib/python3.12/site-packages/pennylane/workflow/qnode.py”, line 895, in call
return self._impl_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/neo-ale-pc/qenv_jl/lib/python3.12/site-packages/pennylane/workflow/qnode.py”, line 868, in _impl_call
res = execute(
^^^^^^^^
File “/home/neo-ale-pc/qenv_jl/lib/python3.12/site-packages/pennylane/workflow/execution.py”, line 238, in execute
results = run(tapes, device, config, inner_transform)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/neo-ale-pc/qenv_jl/lib/python3.12/site-packages/pennylane/workflow/run.py”, line 298, in run
results = inner_execute(tapes)
^^^^^^^^^^^^^^^^^^^^
File “/home/neo-ale-pc/qenv_jl/lib/python3.12/site-packages/pennylane/workflow/run.py”, line 263, in inner_execute
results = device.execute(transformed_tapes, execution_config=execution_config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/neo-ale-pc/qenv_jl/lib/python3.12/site-packages/pennylane_qiskit/qiskit_device.py”, line 83, in execute
results = tracked_execute(self, circuits, execution_config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/neo-ale-pc/qenv_jl/lib/python3.12/site-packages/pennylane/devices/modifiers/simulator_tracking.py”, line 28, in execute
results = untracked_execute(self, circuits, execution_config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/neo-ale-pc/qenv_jl/lib/python3.12/site-packages/pennylane_qiskit/qiskit_device.py”, line 595, in execute
results.append(execute_fn(circ, session))
^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/neo-ale-pc/qenv_jl/lib/python3.12/site-packages/pennylane_qiskit/qiskit_device.py”, line 650, in _execute_estimator
qcirc = [circuit_to_qiskit(circuit, self.num_wires, diagonalize=False, measure=False)]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/neo-ale-pc/qenv_jl/lib/python3.12/site-packages/pennylane_qiskit/converter.py”, line 694, in circuit_to_qiskit
qc &= operation_to_qiskit(op, reg)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/neo-ale-pc/qenv_jl/lib/python3.12/site-packages/pennylane_qiskit/converter.py”, line 746, in operation_to_qiskit
qregs = [reg[i] for i in op_wires.labels]
~~~^^^
IndexError: index out of range

And this is the first part of the code

import time
import pickle
import pennylane as qml
import pennylane.numpy as np
from functools import partial
from ibm_config import service
import matplotlib.pyplot as plt
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_runtime.fake_provider import FakeTorino

from Clifford_compiler import annealing
from convertitore import operator_converter
from metropolis_locale import hubbard_spinful_hamiltonian
from metropolis_locale_nospin import hubbard_spinless_hamiltonian

from qiskit import transpile

def remove_zero_terms(H):
   coeffs_clean, ops_clean = [], []
   for c, o in zip(H.coeffs, H.ops):
       if not qml.math.allclose(c, 0):
           coeffs_clean.append(c)
           ops_clean.append(o)
   return qml.Hamiltonian(coeffs_clean, ops_clean)

backend = FakeTorino()

estimator = Estimator(backend, options={"resilience_level": 2})

Lx, Ly = map(int, input("Inserisci dimensioni reticolo (Lx Ly): ").split())
t, U = map(float, input("Inserisci parametri del sistema (t U): ").split())

with open("hamiltonian_result1.pkl", "rb") as f:
       H = pickle.load(f)  


wire_map = {0:79,1:80,2:78,3:81,4:92,5:77,6:72,7:82,8:59,9:73,10:83,11:58,12:60,13:63,14:61,15:62,16:64,17:54}

H = qml.map_wires(H, wire_map)

physical_qubits = [79,80,78,81,92,77,72,82,59,73,83,58,60,63,61,62,64,54]

start = time.time()

N = Lx * Ly
number_raw = []

for i in range(2*N):
   # Generazione operatori 
   num = operator_converter([(1j*0.5, [2*i, 2*i+1])])
   number_raw.append(num)

number = [qml.map_wires(op, wire_map) for op in number_raw]   

shots = 4000

dev = qml.device(
   "qiskit.remote",
   backend = backend,
   wires = physical_qubits,      
   optimization_level = 3
)


@qml.qnode(dev, shots = shots)
def circuito(time_evol):

   qml.QDrift(H, time=time_evol, n=20)

   return [qml.expval(num) for num in number]
   
print("\nEsecuzione circuito...")
start = time.time()

values = np.array(circuito(0.2))

I tried also this type of format
dev = qml.device( "qiskit.remote", backend = backend, wires = len(physical_qubits), optimization_level = 1, initial_layout = physical_qubits ),
but also in this case it doesn’t work. Interestingly, this exact approach worked when I submitted a job to the IBM backend two weeks ago. I suspect that recent updates to the IBM transpiler might have caused compatibility issues with the qiskit-pennylane plugin.

Hi @Alex1 , thanks for reporting this!

I think you might be right. Would you like to open a bug report in the PennyLane-Qiskit repo? I can open one on your behalf if you prefer. If you do open one please link to this conversation, and share the link to the issue here too in case someone else wants to follow up on the problem.

Thanks if you open a PennyLane-Qiskit repo for me! In the past days I provided to report the bug due to the update also to the IBM center. In any case I solved partially the problem converting the circuit through the qml.tape and than the qml.circuit_to_qiksit method and passing it to the pass_manager with the initial_layout option.

I’m glad you were able to solve it! And thanks for sharing the solution here.

I’ve created the GitHub issue here. I hope we can get to it soon.