question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`Operator.from_circuit` fails on transpiled circuits with user-defined registers

See original GitHub issue

Environment

  • Qiskit Terra version: main @ 293ab43
  • Python version: 3.10
  • Operating system: macOS

What is happening?

Operator.from_circuit throws a “cannot find bit” error when called on a transpiled circuit that was originally constructed out of:

  • more than one register
  • one register with a non-standard name (i.e. not q)
  • loose qubits
  • fewer qubits than the backend

How can we reproduce the issue?

All of these examples print “failed”:

from qiskit import QuantumCircuit, QuantumRegister, transpile
from qiskit.circuit import Qubit
from qiskit.circuit.exceptions import CircuitError
from qiskit.providers.fake_provider import FakeBelem
from qiskit.quantum_info import Operator

backend5q = FakeBelem()

loose_bits = transpile(QuantumCircuit([Qubit() for _ in [None] * 5]), backend5q)
direct_register = transpile(QuantumCircuit(QuantumRegister(5)), backend5q)
two_registers = transpile(
    QuantumCircuit(QuantumRegister(3), QuantumRegister(2)), backend5q
)
not_big_enough = transpile(QuantumCircuit(3), backend5q)

for i, circuit in enumerate(
    (loose_bits, direct_register, two_registers, not_big_enough)
):
    try:
        Operator.from_circuit(circuit)
    except CircuitError:
        print(f"failed {i}")

The actual exception is along the lines of

KeyError                                  Traceback (most recent call last)
~/code/qiskit/terra/qiskit/circuit/quantumcircuit.py in find_bit(self, bit)
   1521             if isinstance(bit, Qubit):
-> 1522                 return self._qubit_indices[bit]
   1523             elif isinstance(bit, Clbit):

KeyError: <qiskit.circuit.quantumregister.Qubit object at 0x122f420c0>

The above exception was the direct cause of the following exception:

CircuitError                              Traceback (most recent call last)
<ipython-input-13-fe6a13093a55> in <module>
     17     (loose_bits, direct_register, two_registers, not_big_enough)
     18 ):
---> 19     Operator.from_circuit(circuit)
     20

~/code/qiskit/terra/qiskit/quantum_info/operators/operator.py in from_circuit(cls, circuit, ignore_set_layout, layout)
    236         # based on that layout
    237         if layout is not None:
--> 238             qargs = {
    239                 phys: circuit.find_bit(bit).index
    240                 for phys, bit in layout.get_physical_bits().items()

~/code/qiskit/terra/qiskit/quantum_info/operators/operator.py in <dictcomp>(.0)
    237         if layout is not None:
    238             qargs = {
--> 239                 phys: circuit.find_bit(bit).index
    240                 for phys, bit in layout.get_physical_bits().items()
    241             }

~/code/qiskit/terra/qiskit/circuit/quantumcircuit.py in find_bit(self, bit)
   1526                 raise CircuitError(f"Could not locate bit of unknown type: {type(bit)}")
   1527         except KeyError as err:
-> 1528             raise CircuitError(
   1529                 f"Could not locate provided bit: {bit}. Has it been added to the QuantumCircuit?"
   1530             ) from err

CircuitError: 'Could not locate provided bit: <qiskit.circuit.quantumregister.Qubit object at 0x122f420c0>. Has it been added to the QuantumCircuit?'

What should happen?

The bits we’re looking up should be the ones that are actually on the circuit.

Any suggestions?

The current form only works (as best as I can tell) with circuits constructed as QuantumCircuit(n), where n is the number of bits in the backend used in the transpilation call. The fact that this works is a side-effect of how the legacy Qubit hash function works, and that the legacy behaviour of QuantumCircuit(n) is to create a register called “q”, which is the same name as what the layout passes create by default.

The _layout field in a circuit from transpile has the same qubits as the input circuit in its “virtual bits” fields, but the returned circuit has a single register called “q” that fills everything. The lookup in Operator.find_circuit tries to use the virtual bits from the original circuit, but these don’t exist any more.

I’m not actually sure if this is recoverable off the top of my head - I’m not certain Layout retains enough information to infer the order the virtual qubits of the previous circuit were in, especially if they are loose bits.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
mtreinishcommented, Sep 28, 2022

I pushed up a fix PR in #8802 and left the property as private for now (and used a tuple) to make sure we could include it in 0.22.0 at this point in the cycle. I’ll open a new issue for 0.23.0 to make a public layout attribute and/or a public method to reverse the layout somehow and we can make a container class for it as part of that

0reactions
jakelishmancommented, Sep 28, 2022

Yeah, or perhaps a dataclass / some custom object that contains the original qubits and the layout? It’s easier to extend an attribute-based object than a tuple if we need to add more later.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Submitting user-transpiled circuits using primitives
This example will take you through the full process of creating, transpiling, and submitting circuits. Transpiling circuits for IBM Quantum devices¶. In the ......
Read more >
Resource Optimal Executable Quantum Circuit Generation ...
3.11 Approximate CNOT circuit with user-defined threshold = 0. ... and multi-qubit quantum gates to the quantum register |ψ〉 (Figure 1.1).
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found