Skip to content

Supporting control flow ops in the Rust circuit drawer #16005

@eliarbel

Description

@eliarbel

This is an expansion of item no. 6 in #15849, containing a proposal about how to visualize control flow instructions and a general discussion about the major changes required to support them in the Rust circuit drawer.

First, regarding visualization, I think it would be nice if we had a way to render control flow items in a slicker way than the multi-wire empty boxes used in the Python text drawer today. Taking inspiration from the MPL drawer, I experimented a bit with manual Unicode drawing and achieved something which IMO looks much better than the textually-rendered output today:

Image
This is the corresponding character rendering, for reference:
                               ╭┄If┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┬┄Else┄╮╭┄Switch┄┬┄Case(0)┄┬┄Case(1,2)┄┬┄Default┄╮
                               ┆┌───┐               ┆      ┆┆        ┆  ┌───┐  ┆   ┌───┐   ┆         ┆
q0_0: ─────────────────────────┼┤ H ├───────────────┼──────┼┼────────┼──┤ X ├──┼───┤ H ├───┼─────────┼─
      ╭┄Box┄┄┄┄┄┄╮             ┆└───┘      ╭┄While┄╮┆      ┆┆        ┆  └───┘  ┆   └───┘   ┆         ┆
      ┆┌───┐     ┆             ┆           ┆ ┌───┐ ┆┆┌───┐ ┆┆        │         ┆           ┆  ┌───┐  ┆
q0_1: ┼┤ H ├──■──┼─────────────┼──■────────┼─┤ X ├─┼┼┤ S ├─┼┼────────┼─────────┼───────────┼──┤ Z ├──┼─
      ┆└───┘  │  ┆╭┄If┄┄┄┄┄┄┄┄╮┆  │        ┆ └─┬─┘ ┆┆└───┘ ┆┆        ┆         ┆           ┆  └───┘  ┆
      ┆     ┌─┴─┐┆┆┌─────────┐┆┆  │        ┆   │   ┆┆┌───┐ ┆╰┄╥┄┄┄┄┄┄┴┄┄┄┄┄┄┄┄┄┴┄┄┄┄┄┄┄┄┄┄┄┴┄┄┄┄┄┄┄┄┄╯
q0_2: ┼─────┤ X ├┼┼┤ Rz(0.3) ├┼┼──■────────┼───■───┼┼┤ T ├─┼──╫────────────────────────────────────────
      ┆     └───┘┆┆└─────────┘┆┆  │        ╰┄╥┄┄┄┄┄╯┆└───┘ ┆  ║
      ┆┌───┐     ┆╰┄╥┄┄┄┄┄┄┄┄┄╯┆┌─┴─┐        ║      ┆      ┆  ║
q0_3: ┼┤ Z ├─────┼──╫──────────┼┤ X ├────────╫──────┼──────┼──╫────────────────────────────────────────
      ┆└───┘     ┆  ║          ┆└───┘        ║      ┆      ┆  ║
      ╰┄┄┄┄┄┄┄┄┄┄╯  ║          ╰┄╥┄┄┄┄┄┄┄┄┄┄┄╫┄┄┄┄┄┄┴┄┄┄┄┄┄╯  ║
                  ┌─╨────────┐ ┌─╨────────┐┌─╨────────┐     ┌─╨───┐
c0: 2/════════════╡ c0_0=0x1 ╞═╡ c0_0=0x0 ╞╡ c0_1=0x1 ╞═════╡ 0x3 ╞════════════════════════════════════
                  └──────────┘ └──────────┘└──────────┘     └─────┘

And this is the Python output, for comparison:

                                                                      ┌──────   ┌───┐                           ┌────────      »
q0_0: ────────────────────────────────────────────────────────────────┤       ──┤ H ├───────────────────────────┤         ─────»
                                                                      │         └───┘                           │              »
      ┌─────── ┌───┐      ───────┐                                    │              ┌─────────  ┌───┐ ───────┐ │         ┌───┐»
q0_1: ┤        ┤ H ├──■──        ├────────────────────────────────────┤       ────■──┤          ─┤ X ├        ├─┤         ┤ S ├»
      │        └───┘  │          │                                    │           │  │           └─┬─┘        │ │         └───┘»
      │             ┌─┴─┐        │   ┌──────   ┌─────────┐ ───────┐   │ If-0      │  │ While-1     │    End-1 │ │ Else-0  ┌───┐»
q0_2: ┤ Box-0  ─────┤ X ├  End-0 ├───┤ If-0  ──┤ Rz(0.3) ├  End-0 ├───┤       ────■──┤          ───■──        ├─┤         ┤ T ├»
      │             └───┘        │   └──╥───   └─────────┘ ───────┘   │           │  └────╥────        ───────┘ │         └───┘»
      │        ┌───┐             │      ║                             │         ┌─┴─┐     ║                     │              »
q0_3: ┤        ┤ Z ├─────        ├──────╫─────────────────────────────┤       ──┤ X ├─────╫─────────────────────┤         ─────»
      └─────── └───┘      ───────┘      ║                             └──╥───   └───┘     ║                     └────────      »
                                   ┌────╨─────┐                     ┌────╨─────┐     ┌────╨─────┐                              »
c0: 2/═════════════════════════════╡ c0_0=0x1 ╞═════════════════════╡ c0_0=0x0 ╞═════╡ c0_1=0x1 ╞══════════════════════════════»
                                   └──────────┘                     └──────────┘     └──────────┘                              »
«       ───────┐ ┌────────── ┌──────────── ┌───┐┌─────────────── ┌───┐┌────────────────       ───────┐ 
«q0_0:         ├─┤           ┤             ┤ X ├┤                ┤ H ├┤                 ─────        ├─
«              │ │           │             └───┘│                └───┘│                              │ 
«              │ │ Switch-0  │ Case-0 (0)       │ Case-0 (1, 2)       │ Case-0 default  ┌───┐  End-0 │ 
«q0_1:         ├─┤           ┤             ─────┤                ─────┤                 ┤ Z ├        ├─
«              │ └────╥───── └────────────      └───────────────      └──────────────── └───┘ ───────┘ 
«        End-0 │      ║                                                                                
«q0_2:         ├──────╫────────────────────────────────────────────────────────────────────────────────
«              │      ║                                                                                
«              │      ║                                                                                
«q0_3:         ├──────╫────────────────────────────────────────────────────────────────────────────────
«       ───────┘      ║                                                                                
«                  ┌──╨──┐                                                                             
«c0: 2/════════════╡ 0x3 ╞═════════════════════════════════════════════════════════════════════════════
«                  └─────┘                                                                             
P

Implementation-wise, here are some initial thoughts about the required changes:

  • Visualization matrix: this is a 2D representation of the circuit, kind of an internal IR between CircuitData and TextDrawer. To continue the design philosophy whereby every visible element has an entry in the visualization matrix, we'll need to introduce a new element for representing control flow frames. For this we should add a new variant to the VisualizationElement enum, called Frame. The new variant should probably hold a reference to the ControlFlowInstruction object of the corresponding PackedInstruction.
  • Layers: build_layers should become aware of the nesting in control flow instructions. Furthermore, I think it could be helpful if build_layers will produce a flattened output, so that all PackedInstruction references, including those inside inner control flow blocks, are already assigned to layers.
  • Conditions: The Boxed variant in VisualizationElement is meant to represent visualization elements on qubit wires only. We should probably not change that but add a new variable, say called Condition, to represent the control flow condition boxes drawn on classical bits.

Metadata

Metadata

Assignees

No one assigned

    Labels

    RustThis PR or issue is related to Rust code in the repositorymod: visualizationqiskit.visualization

    Type

    Projects

    Status

    Ready

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions