Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GatesInBasis analysis pass #6832

Merged
merged 12 commits into from
Oct 13, 2021
Merged

Add GatesInBasis analysis pass #6832

merged 12 commits into from
Oct 13, 2021

Conversation

mtreinish
Copy link
Member

Summary

This commit adds a new analysis pass, GatesInBasis, which is used to
check if all the gates in the circuit are currently in the basis set or
not. The intent for this pass is to use this to conditionally trigger
the execution of basis translation (normally the BasisTranslator) in the
main optimization loop of the preset pass managers, however this is
blocked on #6830. So for now this just adds the pass so we can use it in
the future.

Details and comments

@mtreinish mtreinish requested a review from a team as a code owner July 29, 2021 14:12
This commit adds a new analysis pass, GatesInBasis, which is used to
check if all the gates in the circuit are currently in the basis set or
not. The intent for this pass is to use this to conditionally trigger
the execution of basis translation (normally the BasisTranslator) in the
main optimization loop of the preset pass managers, however this is
blocked on Qiskit#6830. So for now this just adds the pass so we can use it in
the future.
Copy link
Member

@kdk kdk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the whole, this looks good. This is another place where the Gate/Instruction distinction can be hard to reason about (it took longer than I would've expected to try and think if there were any edge cases between Instruction/Gate, op_nodes/gate_nodes, and basis_gates/supported_instructions, but I do think what's here, combined with where it will be run in the optimization loop, is correct.)

I would've expected though the BasisTranslator to effectively be a no-op if the circuit is already in the basis (and effectively have a version of this check implemented already). Is this not the case? Or does this pass perform that check more quickly?

qiskit/transpiler/passes/utils/gates_basis.py Outdated Show resolved Hide resolved
mtreinish and others added 5 commits October 5, 2021 12:06
This commit reworks the GatesInBasis pass to keep track of the
instruction counts in the DAGCircuit object whenever we add or remove
an op node from the DAG. Then the gates in basis pass can simply lookup
against that counts dictionary whether or not all the gates are in the
basis or not. This way we avoid a full dag traversal to determine the
gates in the dag.
Co-authored-by: John Lapeyre <jlapeyre@users.noreply.github.com>
@mtreinish mtreinish added the Changelog: New Feature Include in the "Added" section of the changelog label Oct 5, 2021
@mtreinish mtreinish requested review from jlapeyre and kdk October 5, 2021 20:10
@jlapeyre
Copy link
Contributor

jlapeyre commented Oct 5, 2021

LGTM. Thanks!

jlapeyre
jlapeyre previously approved these changes Oct 5, 2021
Copy link
Member

@kdk kdk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mtreinish , this looks great! Can DAGCircuit.count_ops() use this now? Also, can this be added as a check in test.python.test_dagcircuit.raise_if_dagcircuit_invalid?

qiskit/dagcircuit/dagcircuit.py Outdated Show resolved Hide resolved
qiskit/dagcircuit/dagcircuit.py Show resolved Hide resolved
@mtreinish
Copy link
Member Author

Can DAGCircuit.count_ops() use this now?

Yeah, we can replace the implementation of that with return self._op_names. The only thing is the order might not be the same since we explicitly iterate over the DAG in topological order there while the self._op_names will be in node creation order. If you don't think that's critical I can update it in this PR.

@mtreinish
Copy link
Member Author

Also, can this be added as a check in test.python.test_dagcircuit.raise_if_dagcircuit_invalid?

Done in: 215e008

qiskit/dagcircuit/dagcircuit.py Outdated Show resolved Hide resolved
def run(self, dag):
"""Run the GatesInBasis pass on `dag`."""
gates_out_of_basis = False
basic_instrs = {"measure", "reset", "barrier", "snapshot", "delay"}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for having an extra set of "magic" instructions that always count as being in the basis? Are these ones absolutely guaranteed to always be removed by a later transpiler pass?

If you're looking to ignore directives, it might be better to keep track of the Instruction._directive parameter, but that doesn't fit super nicely with the current set. Alternatively, we could make this an __init__ kwarg, and default to this set if we're not given a value?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just mirroring what the basis_translator does https://github.com/Qiskit/qiskit-terra/blob/main/qiskit/transpiler/passes/basis/basis_translator.py#L85 it's a poor but prevalent assumption the transpiler makes everywhere that these instructions are universal for all backends. (It's something I'm trying to change in #5885 by making the instructions support explicit), but for the time being I couldn't think of any other way to do this. I can add a kwarg but I think it'll just be better to update this for backendv2 when things are ready

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok cool, if it's a baked-in assumption elsewhere in Terra, we may as well leave it as it is for now.

mtreinish and others added 2 commits October 13, 2021 13:46
Co-authored-by: itoko <15028342+itoko@users.noreply.github.com>
jakelishman
jakelishman previously approved these changes Oct 13, 2021
@kdk
Copy link
Member

kdk commented Oct 13, 2021

Can DAGCircuit.count_ops() use this now?

Yeah, we can replace the implementation of that with return self._op_names. The only thing is the order might not be the same since we explicitly iterate over the DAG in topological order there while the self._op_names will be in node creation order. If you don't think that's critical I can update it in this PR.

I'd advocate that the only place we should work to maintain dictionary ordering is where we accept or return an OrderedDict (or otherwise document an expected order). Otherwise, for these cases, we'd need to support (indefinitely?) ordering of returned dictionaries, even if the original ordering was arbitrary.

@mtreinish
Copy link
Member Author

I'd advocate that the only place we should work to maintain dictionary ordering is where we accept or return an OrderedDict (or otherwise document an expected order). Otherwise, for these cases, we'd need to support (indefinitely?) ordering of returned dictionaries, even if the original ordering was arbitrary.

Ok sure, done in: dda9f59

@kdk kdk added the automerge label Oct 13, 2021
@kdk kdk added this to the 0.19 milestone Oct 13, 2021
@mergify mergify bot merged commit 7fb30ba into Qiskit:main Oct 13, 2021
@mtreinish mtreinish deleted the gates-in-basis branch October 13, 2021 20:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants