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

transpilation of dynamic circuit fails with Runtime and fake backends #9717

Closed
kevinsung opened this issue Mar 3, 2023 · 4 comments
Closed
Labels
bug Something isn't working

Comments

@kevinsung
Copy link
Contributor

Environment

  • Qiskit Terra version: c29886d
  • Python version: 3.10.9
  • Operating system: Arch Linux

What is happening?

See title.

How can we reproduce the issue?

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile

qreg = QuantumRegister(1)
creg = ClassicalRegister(1)
circuit = QuantumCircuit(qreg, creg)
q, = qreg
c, = creg
circuit.h(q)
circuit.measure(q, c)
with circuit.if_test((c, 1)):
    circuit.x(q)

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.get_backend("ibm_lagos")
transpile(circuit, backend=backend)  # throws error

from qiskit.providers.fake_provider import FakeLagosV2

backend = FakeLagosV2()
transpile(circuit, backend=backend)  # also throws error
---------------------------------------------------------------------------
TranspilerError                           Traceback (most recent call last)
Cell In[3], line 5
      3 service = QiskitRuntimeService()
      4 backend = service.get_backend("ibm_lagos")
----> 5 transpile(circuit, backend=backend)

File ~/projects/qiskit-terra/qiskit/compiler/transpiler.py:381, in transpile(circuits, backend, basis_gates, inst_map, coupling_map, backend_properties, initial_layout, layout_method, routing_method, translation_method, scheduling_method, instruction_durations, dt, approximation_degree, timing_constraints, seed_transpiler, optimization_level, callback, output_name, unitary_synthesis_method, unitary_synthesis_plugin_config, target, hls_config, init_method, optimization_method, ignore_backend_supplied_default_methods)
    378     for circuit, unique_args in zip(circuits, unique_transpile_args):
    379         transpile_config, pass_manager = _combine_args(shared_args, unique_args)
    380         output_circuits.append(
--> 381             _serial_transpile_circuit(
    382                 circuit,
    383                 pass_manager,
    384                 transpile_config["callback"],
    385                 transpile_config["output_name"],
    386                 transpile_config["backend_num_qubits"],
    387                 transpile_config["faulty_qubits_map"],
    388                 transpile_config["pass_manager_config"].backend_properties,
    389             )
    390         )
    391     circuits = output_circuits
    392 end_time = time()

File ~/projects/qiskit-terra/qiskit/compiler/transpiler.py:474, in _serial_transpile_circuit(circuit, pass_manager, callback, output_name, num_qubits, faulty_qubits_map, backend_prop)
    465 def _serial_transpile_circuit(
    466     circuit,
    467     pass_manager,
   (...)
    472     backend_prop=None,
    473 ):
--> 474     result = pass_manager.run(circuit, callback=callback, output_name=output_name)
    475     if faulty_qubits_map:
    476         return _remap_circuit_faulty_backend(
    477             result,
    478             num_qubits,
    479             backend_prop,
    480             faulty_qubits_map,
    481         )

File ~/projects/qiskit-terra/qiskit/transpiler/passmanager.py:528, in StagedPassManager.run(self, circuits, output_name, callback)
    521 def run(
    522     self,
    523     circuits: Union[QuantumCircuit, List[QuantumCircuit]],
    524     output_name: str = None,
    525     callback: Callable = None,
    526 ) -> Union[QuantumCircuit, List[QuantumCircuit]]:
    527     self._update_passmanager()
--> 528     return super().run(circuits, output_name, callback)

File ~/projects/qiskit-terra/qiskit/transpiler/passmanager.py:228, in PassManager.run(self, circuits, output_name, callback)
    226     return circuits
    227 if isinstance(circuits, QuantumCircuit):
--> 228     return self._run_single_circuit(circuits, output_name, callback)
    229 if len(circuits) == 1:
    230     return self._run_single_circuit(circuits[0], output_name, callback)

File ~/projects/qiskit-terra/qiskit/transpiler/passmanager.py:283, in PassManager._run_single_circuit(self, circuit, output_name, callback)
    271 """Run all the passes on a ``circuit``.
    272 
    273 Args:
   (...)
    280     The transformed circuit.
    281 """
    282 running_passmanager = self._create_running_passmanager()
--> 283 result = running_passmanager.run(circuit, output_name=output_name, callback=callback)
    284 self.property_set = running_passmanager.property_set
    285 return result

File ~/projects/qiskit-terra/qiskit/transpiler/runningpassmanager.py:125, in RunningPassManager.run(***failed resolving arguments***)
    123 for passset in self.working_list:
    124     for pass_ in passset:
--> 125         dag = self._do_pass(pass_, dag, passset.options)
    127 circuit = dag_to_circuit(dag)
    128 if output_name:

File ~/projects/qiskit-terra/qiskit/transpiler/runningpassmanager.py:173, in RunningPassManager._do_pass(self, pass_, dag, options)
    171 # Run the pass itself, if not already run
    172 if pass_ not in self.valid_passes:
--> 173     dag = self._run_this_pass(pass_, dag)
    175     # update the valid_passes property
    176     self._update_valid_passes(pass_)

File ~/projects/qiskit-terra/qiskit/transpiler/runningpassmanager.py:202, in RunningPassManager._run_this_pass(self, pass_, dag)
    199 if pass_.is_transformation_pass:
    200     # Measure time if we have a callback or logging set
    201     start_time = time()
--> 202     new_dag = pass_.run(dag)
    203     end_time = time()
    204     run_time = end_time - start_time

File ~/projects/qiskit-terra/qiskit/transpiler/passes/basis/basis_translator.py:190, in BasisTranslator.run(self, dag)
    185 logger.info(
    186     "Basis translation path search completed in %.3fs.", search_end_time - search_start_time
    187 )
    189 if basis_transforms is None:
--> 190     raise TranspilerError(
    191         "Unable to map source basis {} to target basis {} "
    192         "over library {}.".format(source_basis, target_basis, self._equiv_lib)
    193     )
    195 # Compose found path into a set of instruction substitution rules.
    197 compose_start_time = time.time()

TranspilerError: "Unable to map source basis {('x', 1), ('measure', 1), ('h', 1), ('if_else', 1)} to target basis {'barrier', 'sx', 'measure', 'id', 'snapshot', 'rz', 'delay', 'x', 'cx', 'reset'} over library <qiskit.circuit.equivalence.EquivalenceLibrary object at 0x7f29e6862440>."

What should happen?

It should work.

Any suggestions?

The circuit transpiles successfully if passed a backend from IBMProvider:

from qiskit_ibm_provider import IBMProvider

provider = IBMProvider()
backend = provider.get_backend("ibm_lagos", instance=f"ibm-q-internal/deployed/default")
transpile(circuit, backend=backend)
@kevinsung kevinsung added the bug Something isn't working label Mar 3, 2023
@taalexander
Copy link
Contributor

taalexander commented Mar 3, 2023

These backends need to be updated, possibly with the code here - Qiskit/qiskit-ibm-provider#443

You can temporarily work around this by running:

# Workaround until the `if_else` deployment is fixed.

from qiskit.circuit import IfElseOp

if "if_else" not in backend.target:
    backend.target.add_instruction(IfElseOp, name="if_else")

@kevinsung
Copy link
Contributor Author

I see, so the runtime backend issue needs to be fixed in the runtime repository. I'll open an issue there.

@taalexander
Copy link
Contributor

taalexander commented Mar 3, 2023

Hmm, ultimately I think this is a problem with Terra embedding the jsons that are meant to be interpreted by the Provider. This means the provider logic should be replicated in terra...

IMO, since Terra is backend independent the mock backends for IBM shouldn't even be in this package but rather the Provider package.

@mtreinish
Copy link
Member

I'm going to close this issue because Qiskit/qiskit-ibm-runtime#738 was opened. For more specifics the underlying issue is that the target for the ibm_lagos backend is not reporting that it supports an operation named "if_else" so when the transpiler is trying to compile the circuit it doesn't know what to do with the IfElseOp in the circuit since it can't convert that to something the backend says it supports.

As for the fake backend this also fails but that's correct behavior in my opinion. The snapshot configuration used for FakeLagos doesn't list if_else as a supported operation (since it was made long before the backend could support it). This would be the same error if you tried to compile for FakeTokyo or a similar old fake backend. I expect the bug parsing the json to build the target that @taalexander is mentioning is there if we were to add a fake backend which did say it supported if_else (although it is trivial to fix). But, the consensus is that fake backends will be part of the ibm provider package moving forward (see #9553) so this won't come up.

But, please feel free to reopen this if I'm missing something or there is more to discuss here.

@mtreinish mtreinish closed this as not planned Won't fix, can't repro, duplicate, stale Mar 3, 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
Projects
None yet
Development

No branches or pull requests

3 participants