Circuit diagrams: Group loops #2827
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Feature changes
Loops from user source are now grouped in circuit diagrams.
BEFORE:
AFTER:
All loops (
for,while,repeat/until) are supported. The label is the expression in the loop header, which can be, depending on the loop type, an iterable, a "while" condition, or an "until" condition. e.g.:loop: 0..2loop: i < 2loop: i==2Exception 1: If a loop only has a single iteration, we don't group.
Exception 2: If a loop is "vertical", meaning each iteration of the loop only interacts with a distinct set of qubits, then there is no grouping, since grouping in this case tends to look more confusing than helpful.
Internals
High level circuit diagram pipeline
To recap, this is how circuit diagrams get currently generated.
Q#/OpenQASM gets compiled to (via the compilation pipeline --
qsc_frontend,qsc_lowerererFIR lowerer etc)......FIR gets evaluated and traced (via
qsc_evalEvaluator)......Traces with raw stacks get captured and transformed to (via Circuit Tracer)...
...Traces with logical stacks get transformed to (via Circuit Tracer)...
...
Circuitrepresentation gets serialized to (viaserde-json)......Circuit JSON object gets rendered as (via
circuit-vis)...SVG & HTML circuit diagram
Evaluator changes
Tracing in the Evaluator: The
Tracernow captures the stack ofScopes in addition to the usual call stack (Frames) in the tracing calls. The scope stack includes the stack of current lexical scopes and loops, including iteration count. This allows the circuit tracer to build a comprehensive "logical" stack that includes both call frames and lexical scopes in the source.The evaluator, when in DEBUG configuration, pushes LOOPs as a scope into the
Scopestack. Before this change, we did track each Block as a scope, but not specifically loops. So now when we're in a loop, there is an extraScopein the stack:iteration_countwhich the evaluator is instructed to increment every time it enters the body block of the loop.FIR lowerer changes
FIR: In the execution graph, debug-only nodes are consolidated into a separate
ExecGraphDebugNodeenum, just for legibility.FIR: during lowering, we add some extra data to the execution graph for loops: The a new
PushLoopScopeinstruction to push loop scope, with an attachedExprId(used later by the circuit tracer to look up the loop source code and display the loop label) , and aLoopIterationinstruction that is used to indicate a new iteration of the loop has started.Circuit tracer changes
builder.rs/CircuitTracer: Introduces aLogicalStackwhich is a blended stack of call frames and lexical scopes. This struct is produced by transforming the stack traces passed down from the evaluator into a more "friendly" shape, and it corresponds to the structure that will ultimately be seen in the circuit diagram.circuit.rs/Circuit: TheSourceLocation::Unresolvedenum is a now-unnecessary abstraction that is removed in this change.in
CircuitTracer,finishnow takes both FIR and HIR store to resolve sources and scopescircuit-visHTML rendererTest coverage
compiler/qsc/src/interpret/circuit_tests.rstest direct all the way from Q# to theCircuitrepresentationnpm/qsharp/test/circuits-casestest all the way from Q# to rendered SVG & HTML circuit diagram using the JS/WASM componentcompiler/qsc_circuit/src/builder/tests/logical_stack_trace.rs- this exercises the Q# -> traces pipeline, validating that the evaluator returns expected "logical" stack traces