Skip to content

Custom fake backend stopped working after 0.23 #9592

@1ucian0

Description

@1ucian0

Environment

  • Qiskit Terra version: 0.24.0.dev0+e016f9c
  • Python version: 3.9

What is happening?

The following script creates a custom fake backend and transpiles a QV for it:

import rustworkx as rx

from qiskit.transpiler import Target, InstructionProperties
from qiskit.providers.backend import BackendV2
from qiskit.circuit.library import UGate, ECRGate
from qiskit.circuit import Parameter
from qiskit.circuit.controlflow import IfElseOp


class FakeBackend(BackendV2):

    def __init__(self):
        super().__init__()
        graph = rx.generators.path_graph(3)
        num_qubits = len(graph)
        self._target = Target("Fake backend", num_qubits=num_qubits)
        self._target.add_instruction(UGate(Parameter("theta"), Parameter("phi"), Parameter("lam")),
                                     {(qarg,): None for qarg in range(num_qubits)})
        self._target.add_instruction(IfElseOp, name="if_else")
        self._target.add_instruction(
            ECRGate(),
            {edge: InstructionProperties() for edge in graph.edge_list()},
        )

    @property
    def target(self):
        return self._target

    @property
    def max_circuits(self):
        ...

    @classmethod
    def _default_options(cls):
        ...

    def run(self, circuit, **kwargs):
        ...


backend = FakeBackend()

from qiskit.circuit.library import QuantumVolume
from qiskit.compiler import transpile

qc = QuantumVolume(3, depth=5, seed=12345678942).decompose()
print(transpile(qc, backend=backend))

It works fine in terra 0.23.*, but in current main fails like this:

Traceback (most recent call last):
  File "/<redacted>/qiskit-terra/bug_IfElseOp.py", line 47, in <module>
    print(transpile(qc, backend=backend))
  File "/<redacted>/qiskit-terra/qiskit/compiler/transpiler.py", line 381, in transpile
    _serial_transpile_circuit(
  File "/<redacted>/qiskit-terra/qiskit/compiler/transpiler.py", line 474, in _serial_transpile_circuit
    result = pass_manager.run(circuit, callback=callback, output_name=output_name)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passmanager.py", line 528, in run
    return super().run(circuits, output_name, callback)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passmanager.py", line 228, in run
    return self._run_single_circuit(circuits, output_name, callback)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passmanager.py", line 283, in _run_single_circuit
    result = running_passmanager.run(circuit, output_name=output_name, callback=callback)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/runningpassmanager.py", line 125, in run
    dag = self._do_pass(pass_, dag, passset.options)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/runningpassmanager.py", line 173, in _do_pass
    dag = self._run_this_pass(pass_, dag)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/runningpassmanager.py", line 202, in _run_this_pass
    new_dag = pass_.run(dag)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passes/synthesis/unitary_synthesis.py", line 428, in run
    return self._run_main_loop(
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passes/synthesis/unitary_synthesis.py", line 469, in _run_main_loop
    synth_dag = method.run(unitary, **kwargs)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passes/synthesis/unitary_synthesis.py", line 713, in run
    decomposers2q = self._decomposer_2q_from_target(
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passes/synthesis/unitary_synthesis.py", line 635, in _decomposer_2q_from_target
    supercontrolled_basis = {
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passes/synthesis/unitary_synthesis.py", line 636, in <dictcomp>
    k: v for k, v in available_2q_basis.items() if is_supercontrolled(v)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passes/synthesis/unitary_synthesis.py", line 627, in is_supercontrolled
    kak = TwoQubitWeylDecomposition(Operator(gate).data)
  File "/<redacted>/qiskit-terra/qiskit/quantum_info/operators/operator.py", line 99, in __init__
    raise QiskitError("Invalid input data format for Operator")
qiskit.exceptions.QiskitError: 'Invalid input data format for Operator'

How can we reproduce the issue?

Run the code script.

What should happen?

it should work as it was in 0.23.*

Any suggestions?

No idea. Notice the following:

If you remove self._target.add_instruction(IfElseOp, name="if_else") ( in line 19) also works in 0.23.* and in main fails like this:

Traceback (most recent call last):
  File "/<redacted>/qiskit-terra/bug_IfElseOp.py", line 47, in <module>
    print(transpile(qc, backend=backend))
  File "/<redacted>/qiskit-terra/qiskit/compiler/transpiler.py", line 381, in transpile
    _serial_transpile_circuit(
  File "/<redacted>/qiskit-terra/qiskit/compiler/transpiler.py", line 474, in _serial_transpile_circuit
    result = pass_manager.run(circuit, callback=callback, output_name=output_name)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passmanager.py", line 528, in run
    return super().run(circuits, output_name, callback)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passmanager.py", line 228, in run
    return self._run_single_circuit(circuits, output_name, callback)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passmanager.py", line 283, in _run_single_circuit
    result = running_passmanager.run(circuit, output_name=output_name, callback=callback)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/runningpassmanager.py", line 125, in run
    dag = self._do_pass(pass_, dag, passset.options)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/runningpassmanager.py", line 173, in _do_pass
    dag = self._run_this_pass(pass_, dag)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/runningpassmanager.py", line 202, in _run_this_pass
    new_dag = pass_.run(dag)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passes/synthesis/unitary_synthesis.py", line 428, in run
    return self._run_main_loop(
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passes/synthesis/unitary_synthesis.py", line 469, in _run_main_loop
    synth_dag = method.run(unitary, **kwargs)
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passes/synthesis/unitary_synthesis.py", line 713, in run
    decomposers2q = self._decomposer_2q_from_target(
  File "/<redacted>/qiskit-terra/qiskit/transpiler/passes/synthesis/unitary_synthesis.py", line 639, in _decomposer_2q_from_target
    basis_2q_fidelity = 1 - getattr(available_2q_props[basis_2q], "error", 0.0)
TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'

If you decompose again in line 46 (qc = QuantumVolume(...).decompose().decompose() it works in main.

So, it seems like a problem in unitary_synthesis, which got a recent update in #9175

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions