Skip to content

Conversation

alexanderivrii
Copy link
Member

@alexanderivrii alexanderivrii commented Feb 18, 2025

Summary

AnnotatedOperations allow to define a "controlled" version of a gate when a circuit is being constructed, without having to eagerly synthesize the gate in the process. The actual synthesis is left to the transpiler (and specifically to the HighLevelSynthesis transpiler pass). This offers at least two benefits:

The control method for Gates and QuantumCircuits already accepts the argument annotated which can be either False, True or None, with roughly the following semantics:

  • If False, the annotated version of the gate is not constructed, with the only exception that an annotated=False-controlled version of an AnnotatedOperation is an AnnotatedOperation as well.
  • If True, the annotated operation is constructed, except for gates that implement their own control method, thus an annotated=True-controlled version of an XGate will produce either a CX-Gate, a CCX-Gate, or an MCX-Gate.
  • If None, we attempt to construct an annotated=False-version, but if this fails, such as when the gate is parameterized, we create the annotated=True-version.

In the above, None is the default.

In addition, for backward compatibility (at the time), when a QuantumCircuit is converted to a Gate using the to_gate method, the argument annotated is set to False. Unfortunately, this means that when constructing hierarchical circuits that involve controlled subcircuits, the subcircuits are typically not annotated, preventing potential transpiler optimizations. For example this is the case for the older version of circuits in the circuit library, though this is somewhat improved for the new gate classes when control(annotated=True) is explicitly specified. On the other hand, most of the user circuit are not constructed using annotated=True.

The suggestion here is to change the default behavior to construct annotated versions of a gate (unless the gate implements a custom control method). This is a breaking API change, and in particular if someone now writes my_controlled_custom_gate = my_custom_gate.control(3), the my_controlled_custom_gate will no longer be an instance of ControlledGate. I don't if this can break a lot of user code potentially depend on this isinstance check. In addition, the my_controlled_custom_gate will not have a definition available, one would need to use transpile/HighLevelSynthesis to obtain one.

I would like to discuss if we can add this breaking change to 2.0 or possibly to a later release, and what the migration path for the users should be. Comments are highly welcome.

This PR shows that the number of factual changes within Qiskit is very small: the main difference comes up in visualization, where the name of a ControlledGate-version of a gate is drawn with all letters lowercased, while the name of an AnnotatedOperation-version of a gate is drawn with first letter uppercased (compare "ghz" and "Ghz"); and also the annotated-control SWAP gate is drawn differently.

@alexanderivrii alexanderivrii added this to the 2.0.0 milestone Feb 18, 2025
@alexanderivrii alexanderivrii requested review from nonhermitian and a team as code owners February 18, 2025 15:35
@qiskit-bot
Copy link
Collaborator

One or more of the following people are relevant to this code:

@coveralls
Copy link

Pull Request Test Coverage Report for Build 13394975419

Details

  • 1 of 1 (100.0%) changed or added relevant line in 1 file are covered.
  • 26 unchanged lines in 7 files lost coverage.
  • Overall coverage decreased (-0.02%) to 88.176%

Files with Coverage Reduction New Missed Lines %
crates/qasm2/src/expr.rs 1 94.23%
qiskit/qpy/binary_io/circuits.py 1 91.35%
qiskit/synthesis/unitary/qsd.py 2 95.97%
qiskit/circuit/add_control.py 5 94.07%
qiskit/visualization/circuit/text.py 5 94.56%
crates/qasm2/src/lex.rs 6 92.23%
crates/qasm2/src/parse.rs 6 97.61%
Totals Coverage Status
Change from base Build 13390168524: -0.02%
Covered Lines: 78732
Relevant Lines: 89290

💛 - Coveralls

@1ucian0 1ucian0 modified the milestones: 2.0.0, 2.1.0 Feb 20, 2025
@eliarbel eliarbel modified the milestones: 2.1.0, 3.0.0 Apr 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants