Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transpile problem using DynamicsBackend code #235

Closed
BeomGyuChoii opened this issue Jun 22, 2023 · 5 comments · Fixed by #248
Closed

Transpile problem using DynamicsBackend code #235

BeomGyuChoii opened this issue Jun 22, 2023 · 5 comments · Fixed by #248
Labels
bug Something isn't working

Comments

@BeomGyuChoii
Copy link

Informations

  • Qiskit Dynamics version: 0.4.1
  • Python version: 3.9.15
  • Operating system: Windows

What is the current behavior?

Sorry to my English. Please understand this post.
When I use DynamicsBackend class at fakeprovider, there is variable 'subsystem_list'. Qiskit Document explanation said that 'subsystem_list' means the qubit which i wanted to use.

There are problems. When I use pulse class, If I write 1 or another number except 0 at subsystem_list, there is error.
Also, If I write a list like [0,1], and If I use pulse class at two qubit, there is error.
I described all code below.

Steps to reproduce the problem

I will write my code.

First problem:
from qiskit.providers.fake_provider import FakeKolkata
from qiskit_dynamics.backend import DynamicsBackend
backend= DynamicsBackend.from_backend(FakeKolkata(), subsystem_list=[1])
X_cal=QuantumCircuit(1)
X_cal.x(0)
X_cal.measure_all()
X_cal.calibrations
with pulse.build(backend, name='X') as x_q0:
pulse.play(Drag(duration=160, beta=0.7171287840008055, amp=0.16, sigma=40), pulse.DriveChannel(0))
X_cal.add_calibration('x',[0], x_q0)
circ_transpile = transpile(X_cal, backend)

and there is error
QiskitError: "Cannot unroll the circuit to the given basis, ['measure']. Instruction measure not found in equivalence library and no rule found to expand."

But if i write at subsystem_list = [0], there is not problem.

Second problem:
from qiskit.providers.fake_provider import FakeKolkata
from qiskit_dynamics.backend import DynamicsBackend
backend= DynamicsBackend.from_backend(FakeKolkata(), subsystem_list=[0,1])
circ=QuantumCircuit(2)
circ.h(0)
circ.x(0)
circ.z(1)
circ.cx(0,1)
circ.y(0)
circ.y(1)
circ.measure_all()
with pulse.build(backend, name='X') as x_q0:
pulse.play(Drag(duration=160, beta=-1.5, amp=0.15575757575757576, sigma=40), pulse.DriveChannel(0))
circ.add_calibration('x',[0], x_q0)
with pulse.build(backend, name='Y') as y_q0:
pulse.shift_phase(np.pi,pulse.DriveChannel(0))
pulse.play(Drag(duration=160, beta=-1.5, amp=0.15575757575757576, sigma=40), pulse.DriveChannel(0))
circ.add_calibration('y',[0], y_q0)
with pulse.build(backend, name='Y') as y_q1:
pulse.shift_phase(np.pi,pulse.DriveChannel(1))
pulse.play(Drag(duration=160, beta=-1.5, amp=0.15575757575757576, sigma=40), pulse.DriveChannel(1))
circ.add_calibration('y',[1], y_q1)
circ_transpile = transpile(circ, backend)

and there is problem
TranspilerError: "Unable to translate the operations in the circuit: ['cx', 'z', 'h', 'measure', 'barrier'] to the backend's (or manually specified) target basis: ['barrier', 'measure', 'snapshot']. This likely means the target basis is not universal or there are additional equivalence rules needed in the EquivalenceLibrary being used. For more details on this error see: https://qiskit.org/documentation/stubs/qiskit.transpiler.passes.BasisTranslator.html#translation_errors"

What is the expected behavior?

First case is just drive qubit 1 and yield the result.
Second case also just drive qubit to use our calibrated X gate and Y gate and other qiskit own calibrated gate.

Suggested solutions

Add all our calibration gate to basis gate.

@BeomGyuChoii BeomGyuChoii added the bug Something isn't working label Jun 22, 2023
@DanPuzzuoli
Copy link
Collaborator

Thank you for this bug report! We will try to address it soon and include it in the next patch release.

@DanPuzzuoli
Copy link
Collaborator

DanPuzzuoli commented Jun 22, 2023

Just reproducing the first issue with code that is fully executable:

from qiskit_dynamics import DynamicsBackend
from qiskit import pulse
from qiskit import QuantumCircuit, transpile

from qiskit.providers.fake_provider import FakeKolkata
from qiskit_dynamics.backend import DynamicsBackend




backend= DynamicsBackend.from_backend(FakeKolkata(), subsystem_list=[1])
X_cal=QuantumCircuit(1)
X_cal.x(0)
X_cal.measure_all()
X_cal.calibrations

with pulse.build(backend, name='X') as x_q0:
    pulse.play(
        pulse.Drag(duration=160, beta=0.7171287840008055, amp=0.16, sigma=40), 
        pulse.DriveChannel(1)
    )

X_cal.add_calibration('x',[0], x_q0)
circ_transpile = transpile(X_cal, backend)

I think the issue here is purely to do with labelling. When specifying subsystem_list=[1], DynamicsBackend is only aware that it has a system labelled by index 1 (and it will internally automatically build some measurement definitions based on this labelling). Note that this is different from normal backends, which always assume they have a list of qubit labels of the form [0, 1, ..., num_qubits-1]. When you build your circuit/schedule, everything is done with label 0, so when it looks into the target for definitions of these things, it raises an error (all instructions are labelled with 1). Will need to look deeper to confirm the extent of this, and better understand how the labels behave in transpilation to determine the correct solution to this.

@DanPuzzuoli
Copy link
Collaborator

The second issue isn't actually an issue, it is a design choice. DynamicsBackend.from_backend does not import the gate definitions from the backend passed to it. This is explained in the from_backend method documentation. As such, the backend in your second example doesn't have internal definitions for any of the gates you're using in your circuit.

For some more context behind this choice: It is a reaction to the from_backend method of the PulseSimulator in Aer, which did import the pulse definitions. Due to mismatches in the reported model and the actual device, the pre-existing backend pulses will not perform well in simulation, which confused users. To use a simulation-based pulse backend, it is necessary to actually run through calibration procedures just like on a real backend to "bring up" the device, as is partially done in the DynamicsBackend tutorial.

@mtreinish
Copy link
Contributor

In general a target defines the qubit indices as a contiguous set starting at 0. So if you're creating a target with gates that are only defined on qubit 1 you'll end up with a 2 qubit backend where nothing is supported on qubit 0. In newer versions of qiskit (qiskit-terra>=0.24.0) I'd expect this actually work ok with: Qiskit/qiskit#9927 the transpiler will ignore qubits (i.e. treat them as non-operational/not available) if there are no instructions listed in the target that operate on them (assuming you define the calibration for the gate on the correct qubit). If the intent behind:

backend= DynamicsBackend.from_backend(FakeKolkata(), subsystem_list=[1])

is to have backend be a 1 qubit backend, then you'll need to reindex the target based on the number of qubits you want.

@DanPuzzuoli
Copy link
Collaborator

I think I potential solution to this is to change the behaviour of the subsystem_list argument of from_backend so that all qubits of the original backend are "kept", but all of the qubits not in subsystem_list are treated as 1-dimensional systems. I don't think this will actually change anything about the internal functioning of DynamicsBackend, and should hopefully make the target behave better (as now we can always have qubits with labelling [0, ..., n-1]).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants