Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add internal routine for canonicalisation of control-flow builders (#…
…8627) * Add canonical form for control-flow builders This adds an internal function for use in tests that puts circuits constructed with the control-flow builders into a canonical form. There are several non-determinstic components to the control-flow builders, since they internally track their resources with hashmaps, and at the end pick an arbitrary order to sequence their arguments in. The order is not likely to be the same between a circuit constructed manually and one constructed by a builder, even though they describe the same dynamics. For-loops with automatically generated loop variables (the `with qc.for_loop(indices) as param: ...` form) will also vary between circuits, as a unique parameter is constructed each time a new one is requested to avoid collisions. The canonicalisation routine uses a shared iterable of parameters that always returns the exact instances in the same order. Replacing the loop variable with a new name has no effect, since it is logically scoped to the loop only and the operation is effectively lambda-calculus-like alpha conversion. This canonicalisation routine is very slow and inefficient, so is only intended for ease in writing tests. Making the builders always output a canonical order would add unnecessary overhead to them for most cases, and the loop-parameter canonicalisation would potentially cause problems if one control-flow built circuit was nested somehow within another (such as by `QuantumCircuit.compose`), as the loop variables could clash (and would violate the canonical form anyway). * Fix non-deterministic DAGCircuit.__eq__ The bits-in-registers equality check previously constructed a sequence of `(name, bit_indices)` tuples using the `dict.items()` iterator. This is unnecessarily insertion-order dependent for registers (in CPython, non-deterministic in general). Instead, we can compare two dictionaries, which will correctly check key-by-key without needing the creation order to match. * Use canonicalisation instead of custom equivalence in builder tests The builder tests previously used a custom circuit-equality checker, which somewhat separated them from other circuit-equality tests. Using the control-flow aware canonicalisation routine first lets us rewrite the circuit using simple rules that clearly don't change the semantics of the circuit, and then use the regular equality checkers. This swap over turned up a bug in the previous iteration of the tests (in the "expected" results!), where the bits of two block bodies were not ordered the same as the arguments to those operations. This commit also corrects those. * Make initial recursive call clearer Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
- Loading branch information