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

Fix OpenQASM 2 gate definitions following a shadowed built-in gate #13340

Merged
merged 1 commit into from
Oct 22, 2024

Conversation

jakelishman
Copy link
Member

Summary

Previously, when given an OpenQASM 2 program such as

OPENQASM 2.0;
gate builtin a { U(0, 0, 0) a; }
gate not_builtin a { U(pi, pi, pi) a; }
qreg q[1];

not_builtin q[0];

and a set of custom_instructions including a builtin=True definition for builtin (but not for not_builtin), the Rust and Python sides would get themselves out-of-sync and output a gate that matched a prior definition, rather than not_builtin.

This was because the Rust side was still issuing DefineGate bytecode instructions, even for gates whose OpenQASM 2 definitions should have been ignored, so Python-space thought there were more gates than Rust-space thought there were.

Details and comments

Fix #13339.

Previously, when given an OpenQASM 2 program such as

    OPENQASM 2.0;
    gate builtin a { U(0, 0, 0) a; }
    gate not_builtin a { U(pi, pi, pi) a; }
    qreg q[1];

    not_builtin q[0];

and a set of `custom_instructions` including a `builtin=True` definition
for `builtin` (but not for `not_builtin`), the Rust and Python sides
would get themselves out-of-sync and output a gate that matched a prior
definition, rather than `not_builtin`.

This was because the Rust side was still issuing `DefineGate` bytecode
instructions, even for gates whose OpenQASM 2 definitions should have
been ignored, so Python-space thought there were more gates than
Rust-space thought there were.
@jakelishman jakelishman added stable backport potential The bug might be minimal and/or import enough to be port to stable Changelog: Bugfix Include in the "Fixed" section of the changelog mod: qasm2 Relating to OpenQASM 2 import or export labels Oct 17, 2024
@jakelishman jakelishman added this to the 1.2.5 milestone Oct 17, 2024
@jakelishman jakelishman requested a review from a team as a code owner October 17, 2024 14:20
@qiskit-bot
Copy link
Collaborator

One or more of the following people are relevant to this code:

  • @Qiskit/terra-core

@coveralls
Copy link

Pull Request Test Coverage Report for Build 11386911964

Details

  • 6 of 6 (100.0%) changed or added relevant lines in 1 file are covered.
  • 22 unchanged lines in 2 files lost coverage.
  • Overall coverage decreased (-0.02%) to 88.643%

Files with Coverage Reduction New Missed Lines %
crates/qasm2/src/lex.rs 4 91.98%
crates/qasm2/src/parse.rs 18 96.69%
Totals Coverage Status
Change from base Build 11383196578: -0.02%
Covered Lines: 73174
Relevant Lines: 82549

💛 - Coveralls

self.symbols.insert(name, symbol.into());
self.num_gates += 1;
Ok(true)
Ok(false)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is probably me missing something, because it looks like the tests pass, but if the gate isn't a built-in, shouldn't the function return Ok(True) because it needs a definition?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's just off the top of the diff, but this is in an if block for a gate that's already in the "overrideable gates" symbol table, which requires the user to have given a constructor function to the Python-space entry point in custom_instructions. So it's already got a gate index allocated, and Python space knows how to construct it.

A "built in" here is meaning "pretend that the gate was always defined in OpenQASM 2", whereas "not a built in" means "use this function to construct the gate, but only allow it if you see a gate statement with its name (but ignore the body of that statement)". We're in the second case here - we don't need to return the body of the gate statement to Python space, because we're ignoring it; we just want to assign the gate index of the overrideable gate to the now properly defined symbol.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks! That makes sense, and is what I suspected, but wanted to make sure I was understanding it right.

Copy link
Contributor

@ElePT ElePT left a comment

Choose a reason for hiding this comment

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

LGTM for what I can see!

@jakelishman jakelishman added this pull request to the merge queue Oct 22, 2024
Merged via the queue into Qiskit:main with commit 9a1d8d3 Oct 22, 2024
15 checks passed
mergify bot pushed a commit that referenced this pull request Oct 22, 2024
#13340)

Previously, when given an OpenQASM 2 program such as

    OPENQASM 2.0;
    gate builtin a { U(0, 0, 0) a; }
    gate not_builtin a { U(pi, pi, pi) a; }
    qreg q[1];

    not_builtin q[0];

and a set of `custom_instructions` including a `builtin=True` definition
for `builtin` (but not for `not_builtin`), the Rust and Python sides
would get themselves out-of-sync and output a gate that matched a prior
definition, rather than `not_builtin`.

This was because the Rust side was still issuing `DefineGate` bytecode
instructions, even for gates whose OpenQASM 2 definitions should have
been ignored, so Python-space thought there were more gates than
Rust-space thought there were.

(cherry picked from commit 9a1d8d3)
@jakelishman jakelishman deleted the qasm2/builtin-gate branch October 22, 2024 13:43
github-merge-queue bot pushed a commit that referenced this pull request Oct 22, 2024
#13340) (#13352)

Previously, when given an OpenQASM 2 program such as

    OPENQASM 2.0;
    gate builtin a { U(0, 0, 0) a; }
    gate not_builtin a { U(pi, pi, pi) a; }
    qreg q[1];

    not_builtin q[0];

and a set of `custom_instructions` including a `builtin=True` definition
for `builtin` (but not for `not_builtin`), the Rust and Python sides
would get themselves out-of-sync and output a gate that matched a prior
definition, rather than `not_builtin`.

This was because the Rust side was still issuing `DefineGate` bytecode
instructions, even for gates whose OpenQASM 2 definitions should have
been ignored, so Python-space thought there were more gates than
Rust-space thought there were.

(cherry picked from commit 9a1d8d3)

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
@jakelishman jakelishman modified the milestones: 1.2.5, 1.3.0 Nov 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: Bugfix Include in the "Fixed" section of the changelog mod: qasm2 Relating to OpenQASM 2 import or export stable backport potential The bug might be minimal and/or import enough to be port to stable
Projects
None yet
Development

Successfully merging this pull request may close these issues.

from_qasm_str not importing Fswap correctly
4 participants