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

runtime job fails when binding multiple parameters with pulse gates #666

Closed
nbronn opened this issue Dec 27, 2022 · 3 comments
Closed

runtime job fails when binding multiple parameters with pulse gates #666

nbronn opened this issue Dec 27, 2022 · 3 comments
Labels
bug Something isn't working priority: high High priority issue (must have for current release)

Comments

@nbronn
Copy link
Collaborator

nbronn commented Dec 27, 2022

Describe the bug

When binding multiple Parameters, i.e. by using a ParameterVector or a circuit generated by TwoLocal, with pulse gates, i.e. those generated by RZXCalibrationBuilder, the following error occurs when running the job via the Sampler:

qiskit.providers.exceptions.JobError: 'Unable to retrieve result for job sampler_cektfmliubo4gdosfftg_a89a_0. Job has failed: Instruction rzx is not supported. Error code: 7001.'

Steps to reproduce

The following code runs successfully for the first circuit and fails for the second:

from qiskit import transpile
from qiskit.circuit import ParameterVector, QuantumCircuit
from qiskit.converters import circuit_to_dag, dag_to_circuit
from qiskit.pulse import Play, ScheduleBlock
from qiskit.quantum_info import Operator
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import RZXCalibrationBuilder
from qiskit_ibm_runtime import QiskitRuntimeService, Session, Sampler, Options
from qiskit_ibm_runtime.options import EnvironmentOptions, ExecutionOptions, TranspilationOptions

from copy import deepcopy
import numpy as np

service = QiskitRuntimeService(channel='ibm_quantum')
backend = service.backend("ibm_perth")

inst_sched_map = backend.defaults().instruction_schedule_map
channel_map = backend.configuration().qubit_channel_mapping

rng = np.random.default_rng(12345)
param_bind = rng.uniform(-np.pi, np.pi, 5)

qc1 = QuantumCircuit(2)
qc1.rx(param_bind[0], 0)
qc1.rx(param_bind[1], 1)
qc1.rz(param_bind[2], 0)
qc1.rz(param_bind[3], 1)
qc1.rzx(param_bind[4], 0, 1)
qc1.draw()

yields

     ┌─────────────┐┌────────────┐┌────────────────┐
q_0: ┤ Rx(-1.7132) ├┤ Rz(1.8684) ├┤0               ├
     ├─────────────┤├────────────┤│  Rzx(-0.68418) │
q_1: ┤ Rx(-1.1513) ├┤ Rz(1.1074) ├┤1               ├
     └─────────────┘└────────────┘└────────────────┘

and

qc2 = QuantumCircuit(2)
thetas = ParameterVector('θ', 5)
qc2.rx(thetas[0], 0)
qc2.rx(thetas[1], 1)
qc2.rz(thetas[2], 0)
qc2.rz(thetas[3], 1)
qc2.rzx(thetas[4], 0, 1)
qc2.draw()

yields similarly

     ┌──────────┐┌──────────┐┌────────────┐
q_0: ┤ Rx(θ[0]) ├┤ Rz(θ[2]) ├┤0           ├
     ├──────────┤├──────────┤│  Rzx(θ[4]) │
q_1: ┤ Rx(θ[1]) ├┤ Rz(θ[3]) ├┤1           ├
     └──────────┘└──────────┘└────────────┘

and

pm = PassManager(RZXCalibrationBuilder(inst_sched_map, channel_map))

qc1_t = transpile(pm.run(qc1), backend)
qc2_t = transpile(pm.run(qc2.assign_parameters(param_bind)), backend)
print(Operator(qc1_t).equiv(Operator(qc2_t)))

is True. The following block is a workaround for Runtime Issue #657:

def replace_pulse_name(block):
    if isinstance(block, ScheduleBlock):
        for blk in block.blocks:
            replace_pulse_name(blk)
    elif isinstance(block, Play):
        if block.pulse._pulse_type == "Drag":
            block.pulse._pulse_type = "realDrag"
        elif block.pulse._pulse_type == "GaussianSquare":
            block.pulse._pulse_type = "realGaussianSquare"
    return

dag1 = deepcopy(circuit_to_dag(qc1_t))
for _, val in dag1._calibrations['rzx'].items():
    replace_pulse_name(val)

dag2 = deepcopy(circuit_to_dag(qc2_t))
for _, val in dag2._calibrations['rzx'].items():
    replace_pulse_name(val)
    
qc1_new = dag_to_circuit(dag1)
qc1_new.measure_all()
qc2_new = dag_to_circuit(dag2)
qc2_new.measure_all()

Then the job is run via

service = QiskitRuntimeService(channel='ibm_quantum')
options = Options(
    optimization_level=0, 
    resilience_level=0, 
    execution=ExecutionOptions(shots=1000, init_qubits=True),
    environment=EnvironmentOptions(job_tags=[f'test-rzx-pulse-gate'], log_level='INFO'),
    transpilation=TranspilationOptions(skip_transpilation=True)
)

with Session(service=service, backend=backend):
    sampler = Sampler(options=options)
    sampler.run(qc1_new)
    sampler.run(qc2_new)

Interestingly, these both run successfully when only using a ParameterVector of length 1 with a single rzx pulse gate.

Expected behavior

Both circuits should run successfully with the Sampler because they are equivalent, as they do when using backend.run().

Suggested solutions

My feeling is that something in the Parameter binding process is causing the primitive to not recognize the attached pulse gate.

Additional Information

  • qiskit-ibm-runtime version: 0.8.0
  • qiskit-terra version: 0.23.0.dev0+dd7f939
  • Python version: 3.9.13
  • Operating system: Darwin
@nbronn nbronn added the bug Something isn't working label Dec 27, 2022
@jyu00 jyu00 added the priority: high High priority issue (must have for current release) label Feb 3, 2023
@kt474 kt474 added this to the 0.9.0 milestone Feb 7, 2023
@kt474 kt474 modified the milestones: 0.9.0 , 0.9.1 Feb 20, 2023
@kt474 kt474 modified the milestones: 0.9.1, 0.9.2 Feb 28, 2023
@kt474
Copy link
Member

kt474 commented Mar 6, 2023

@jakelishman can you take a look? Is this a qpy issue?

@jakelishman
Copy link
Member

I had a dig, and yeah, I think this is a problem in QPY, though I'm suspicious that the real cause is sympy/symengine being not quite as precise as Python when displaying floats as text. With Python, if you need, you can rely on float(str(x)) == x for all x (except for nan which satisfies nan != nan per the IEEE-754 spec). I've opened the issue linked above on Terra to track.

@kt474 kt474 removed this from the 0.9.2 milestone Mar 11, 2023
@kt474
Copy link
Member

kt474 commented Sep 4, 2023

I believe this has been resolved, as the linked issue above has been fixed. Closing for now, feel free to reopen if it's still an issue

@kt474 kt474 closed this as completed Sep 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working priority: high High priority issue (must have for current release)
Projects
None yet
Development

No branches or pull requests

4 participants