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

Combine circuits with clbits onto those with none #7823

Merged
merged 19 commits into from
Jun 28, 2022
Merged

Combine circuits with clbits onto those with none #7823

merged 19 commits into from
Jun 28, 2022

Conversation

nonhermitian
Copy link
Contributor

@nonhermitian nonhermitian commented Mar 27, 2022

fixes #6816

Summary

Allows for the common situation where one combines circuits with measurements (clbits) to those without. Currently you can do this by reversing the order of combine but that is not intuitive at all. Given that many (if not the vast majority) workflows involve the situation described in #6816, it makes sense to allow it. It also requires minimal modifications to do so.

Details and comments

@nonhermitian nonhermitian requested a review from a team as a code owner March 27, 2022 11:15
@nonhermitian nonhermitian changed the title [WIP] Combine circuits with clbits onto those with none Combine circuits with clbits onto those with none Mar 27, 2022
Copy link
Member

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry this took a while. This generally looks fine to me as a special case utility. Please could you add a "feature" release note as well, and a test of this compose path with registerless clbits?

qiskit/circuit/quantumcircuit.py Outdated Show resolved Hide resolved
@nonhermitian
Copy link
Contributor Author

@jakelishman I think this is done now. Incorporating registerless bits was a bit tricky because they can be arbitrarily mixed and matched with registers. As there is no (not deprecated or raising) way of querying if a bit has a register, I basically had to resort to looping over bits to see if they are in any registers.

@jakelishman
Copy link
Member

jakelishman commented Jun 24, 2022

As there is no (not deprecated or raising) way of querying if a bit has a register

There is now, though it wasn't added when the original registerless bits implementation was added for some reason. You can do qc.find_bit(bit).registers to find all tuples of register, index that the bit is in. In this case, though, the extra logic isn't necessary: add_register already does it, and won't add bits that are already in the circuit. The example suggestion I made inline should have worked verbatim, even with bits that are in registers (if it didn't, it's a bug).

@nonhermitian
Copy link
Contributor Author

add_register already does it, and won't add bits that are already in the circuit.

add_register will raise if given a register that already exists in the circuit. So I can't just loop over bits and add to clbits or do add_register. This is is basically why there are two loops in my solution; I need to see if a bit is registerless or not, and make sure I didn't already add the register when looking at earlier bits.

@jakelishman
Copy link
Member

jakelishman commented Jun 27, 2022

add_register raises if a register is already in a circuit, but add_bit does not add any containing register, nor should it, because bits can be in multiple registers, and registers don't own bits. The solution I wrote should have worked verbatim. For example:

In [8]: from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
   ...: qr = QuantumRegister(5)
   ...: cr = ClassicalRegister(5)
   ...: qc = QuantumCircuit()
   ...: qc.add_bits(qr[0:3])
   ...: qc.add_bits(cr[2:4])
   ...: qc.qregs, qc.cregs
Out[8]: ([], [])

In [9]: qc.qubits, qc.clbits
Out[9]:
([Qubit(QuantumRegister(5, 'q3'), 0),
  Qubit(QuantumRegister(5, 'q3'), 1),
  Qubit(QuantumRegister(5, 'q3'), 2)],
 [Clbit(ClassicalRegister(5, 'c3'), 2), Clbit(ClassicalRegister(5, 'c3'), 3)])

In [10]: qc.add_register(qr)
    ...: qc.add_register(cr)
    ...: # Some of the bits from these registers are already in the circuit,
    ...: # but neither of these calls raise.
    ...: qc.qregs, qc.cregs
Out[10]: ([QuantumRegister(5, 'q3')], [ClassicalRegister(5, 'c3')])

In [11]: qc.qubits, qc.clbits
Out[11]:
([Qubit(QuantumRegister(5, 'q3'), 0),
  Qubit(QuantumRegister(5, 'q3'), 1),
  Qubit(QuantumRegister(5, 'q3'), 2),
  Qubit(QuantumRegister(5, 'q3'), 3),
  Qubit(QuantumRegister(5, 'q3'), 4)],
 [Clbit(ClassicalRegister(5, 'c3'), 2),
  Clbit(ClassicalRegister(5, 'c3'), 3),
  Clbit(ClassicalRegister(5, 'c3'), 0),
  Clbit(ClassicalRegister(5, 'c3'), 1),
  Clbit(ClassicalRegister(5, 'c3'), 4)])

If we needed the extra checks, the QuantumCircuit.find_bit function I mentioned above can be used to avoid the quadratic complexity of the nested for-loops, but this is effectively already what add_register does.

@nonhermitian
Copy link
Contributor Author

Ok yeah, I was confused I guess. I updated the code.

Copy link
Member

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries - thanks for the tests Paul, it looks good, and it's a nice convenience feature.

@jakelishman jakelishman added the Changelog: New Feature Include in the "Added" section of the changelog label Jun 28, 2022
@mergify mergify bot merged commit 1082240 into Qiskit:main Jun 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cannot compose circuits with different numbers of measurements
2 participants