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

feat: handle IfElseOp in qiskit_to_tk #437

Draft
wants to merge 33 commits into
base: main
Choose a base branch
from
Draft

feat: handle IfElseOp in qiskit_to_tk #437

wants to merge 33 commits into from

Conversation

CalMacCQ
Copy link
Contributor

@CalMacCQ CalMacCQ commented Dec 17, 2024

Description

Converting a qiskit IfElseOp as two conditional pytket CircBoxes. This sort of control flow is probably better expressed in the HUGR data structure than as a pytket Circuit/CircBox.

Needs more diverse test cases before merging and we also need to decide if we want to handle more complex conditions.

Looking at the qiskit docs they also have switch-case as well as for and while loops which we may want to support in the future.

https://docs.quantum.ibm.com/guides/classical-feedforward-and-control-flow

Example

# define qiskit program
qubits = QuantumRegister(2)
clbits = ClassicalRegister(2)
circuit = QuantumCircuit(qubits, clbits)
(q0, q1) = qubits
(c0, c1) = clbits

circuit.h(q0)
circuit.measure(q0, c0)

with circuit.if_test((c0, 1)) as else_:
    circuit.h(q1)
with else_:
    circuit.x(q1)
circuit.measure(q1, c1)

Now the corresponding pytket circuit looks like

tkc = qiskit_to_tk(circuit)

circuit

The If and Else boxes contain a single $H$ and $X$ gate respectively.

I thought about putting string representing the conditon inside the "If" label however this could be awkward. Hopefully its clear from the diagram whats going on.

This conversion ended up being slighly tricker than I expected because the qiskit circuits which define the true_body and false_body do not have registers. Managed to get around this by using the register from the circuit containing the IfElseOp and cleaning up empty wires with Circuit.remove_blank_wires to ensure the CircBox is of the correct size.

Related issues

closes #415, #366

Checklist

  • I have performed a self-review of my code.
  • I have commented hard-to-understand parts of my code.
  • I have made corresponding changes to the public API documentation.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have updated the changelog with any user-facing changes.

@CalMacCQ CalMacCQ requested a review from cqc-melf as a code owner December 17, 2024 14:37
@CalMacCQ CalMacCQ marked this pull request as draft December 17, 2024 14:55
) -> Circuit:
if_box, else_box = _pytket_boxes_from_IfElseOp(if_else_op, qregs, cregs)
circ_builder = CircuitBuilder(qregs, cregs)
circ = circ_builder.circuit()
Copy link
Contributor

Choose a reason for hiding this comment

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

print(circ.qubits, circ.bits)
print(if_box.get_circuit().qubits, if_box.get_circuit().bits)
print(qubits)
print(bits)

prints

[q105[0], q105[1]] [c3[0], c3[1]]
[q105[0], q105[1]] [c3[0], c3[1]]
[q105[1]]
[c3[0]]

So the box has 2 qubits and 2 bits, but in add_circbox, args=qubits + bits only provides 1 qubit and 1 bit.

Copy link
Contributor Author

@CalMacCQ CalMacCQ Dec 31, 2024

Choose a reason for hiding this comment

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

Thanks.

I figured out what I was doing wrong. The thing that was confusing me was that the two circuits which define the IfElseOp do not have any registers. Their qubits are tied to the register of the circuit containing the IfElseOp. This meant that the subcircuits in my CircBoxes had too many qubits/bits as there were some additional blank wires.

Cleaning up the blank wires with Circuit.remove_blank_wires as in d65a347 seems to fix this.

@CalMacCQ
Copy link
Contributor Author

CalMacCQ commented Dec 31, 2024

The test case I added is now working after 52458ab.

I'll need to add more diverse test cases before I'm confident in merging this as well as negate the "else" condition properly and see what the story is for more complex conditions.

@CalMacCQ CalMacCQ changed the title [DRAFT] feat: handle IfElseOp in qiskit_to_tk feat: handle IfElseOp in qiskit_to_tk Dec 31, 2024
@CalMacCQ CalMacCQ added enhancement New feature or request circuit_conversion Issues and pull requests related to coverting qiskit circuits to pytket and vice versa labels Jan 1, 2025
# Examples -> https://docs.quantum.ibm.com/guides/classical-feedforward-and-control-flow
def _pytket_boxes_from_ifelseop(
if_else_op: IfElseOp, qregs: list[QuantumRegister], cregs: list[ClassicalRegister]
) -> tuple[CircBox, Optional[CircBox]]:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not so pleased with this Optional return type in the function signature. This is to deal with the case when the IfElseOp only has a true_body rather than a true_body and a false_body.

There's probably a cleaner way to deal with this.

circuit.measure(q1, c1)

tkc = qiskit_to_tk(circuit)
assert tkc.n_gates_of_type(OpType.Conditional) == 2
Copy link
Contributor Author

@CalMacCQ CalMacCQ Jan 2, 2025

Choose a reason for hiding this comment

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

Should test this more thoroughly. I ran into this bug -> CQCL/tket#1726 when trying to validate the contents of the two CircBoxes.

args=qubits,
condition_bits=bits,
# TODO: handle conditions over multiple bits/registers?
condition_value=not bool(if_else_op.condition[1]),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Still need to decide if its worth handling more complex conditionals here or just restrict to conditions over a single bit for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
circuit_conversion Issues and pull requests related to coverting qiskit circuits to pytket and vice versa enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support QuantumCircuit.if_test in qiskit_to_tk
3 participants