Open MattePalte opened 2 years ago
Right now, transpile
is purely for complete quantum programs; you say you want to use it on a subcomponent, but right now that's not a supported use. In the context of an entire program, there is no semantic violation here. Our documentation on this expectation could certainly be better, though.
Compilation of subcomponents is something that has come up a couple of times before, and it may be something we want to support in the future. It's not immediately obvious as to how this would work, though; various things like routing, layout and scheduling need to know the exact register allocations, and a lot of optimisations need to know what swaps/couplings will be in place in order to rearrange gates. Even if we did the initial basis translation on a subcomponent, it couldn't actually be re-used safely unless it was laid out onto specific qubits and then only applied to that exact same set, and even then it would need to be scheduled before it could run.
Environment
What is happening?
I define a a sub-circuit without any measurement (since it is intended as sub-component); this sub-circuit ends with a swap gate, then I optimize the sub-circuit (optimization level=3) before using it as building block for a larger circuit/algorithm. But this optimization drops my final swap gate and leaves me with a semantically different sub-circuit with respect to the initial one I wrote. Thus the optimization is modifying the semantic in this context.
How can we reproduce the issue?
I transpile with level 0 and I get the expected result:
Running it with level 3 instead, drops my swap and gives a semantically different circuit, with different result.
What should happen?
I would have expected the optimization to preserve the semantic of the input circuit.
Any suggestions?
Via interactive debugging I nailed down the problem to the optimization pass
OptimizeSwapBeforeMeasure
. This removes the swap before measurement and the swaps which are before final nodesDAGOutNode
(aka end of the circuit). But in this way we are assuming that there will be never be any measurement, which in case of sub-component this is not true. Thus I suggest to remove this optimization for the swap followed byDAGOutNode
nodes, because we cannot guarantee a perfectly semantically equivalent circuit.https://github.com/Qiskit/qiskit-terra/blob/fcec842f1de9fd12120e30a1bf73bf7c52b1bf81/qiskit/transpiler/passes/optimization/optimize_swap_before_measure.py#L45
Going back to my bug-triggering code, if the measurement would have been included in the circuit before the transpile call it would have worked perfectly, but sometimes we might not know how this sub-circuit will be reused in other parts of our algorithm.