Skip to content

Commit

Permalink
Rewrite OpenQASM 3 exporter symbol table (#12776)
Browse files Browse the repository at this point in the history
* Rewrite OpenQASM 3 exporter symbol table

This rewrites the symbol handling of the OpenQASM 3 exporter to decouple
object identities from the necessary object identifiers.  As part of
this, we use the same trick of standard-gate reparametrisation to
produce gate-definition sources for Qiskit built-ins, which fixes many
cases of bad parametrisation of gates like `rzx`.

This kind of rewrite was necessary to fix the now-bad assumption within
the OQ3 exporter that "gate identity" is always static within a circuit.
Since standard gate `Gate` instances are now only generated on demand,
there is no guarantee of stability of them.  The fix to the definition
source for these makes them independent of object identity.
User-defined gates can still use the identity, as these are still
guaranteed static.

This commit fixes almost all of the "bad parametrisation" tests in the
test suite.  There are several other changes in the test suite
necessary:

* since the uniqueness of the identifier is now independent of how the
  lookup of a Qiskit object works, there is no need to include the
  highly non-deterministic `id` in the generated symbols for user gates.
  Several tests changed to use the new, simple count-based unique names.

* the escaping and uniqueness rules now apply uniformly to all gate
  definitions, fixing several bad test cases that previously were
  testing invalid OpenQASM 3.

* the escaping rules changed slightly for naming collisions with
  keywords, making them slightly more consistent with how other renaming
  rules worked.

* Add test for bug fix for issue #7335

* Rename qiskit gates whose names are OQ3 hardware qubit identifiers

If a custom qiskit gate is given a name that is a valid identifer for a
hardware qubit in OQ3, then, before this commit, the name would not be
escaped when writing the OQ3 gate definition.

This commit fixes this by escaping the leading dollar sign as it would
be in any other position in the name. That is, the dollar sign is
replaced by underscore.

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>

* Reduce overloading of word "definition"

Much of what we're doing with the "definition source" is actually a form
of object canonicalisation for comparison purposes.  It's clearer to use
this terminology.

* Remove unnecessary getattr

* Fix isinstance/issubclass naming

---------

Co-authored-by: John Lapeyre <jlapeyre@users.noreply.github.com>
  • Loading branch information
jakelishman and jlapeyre authored Jul 22, 2024
1 parent ce6f929 commit 59fc495
Show file tree
Hide file tree
Showing 6 changed files with 881 additions and 938 deletions.
10 changes: 10 additions & 0 deletions crates/circuit/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,16 @@ impl StandardGate {
pub fn get_name(&self) -> &str {
self.name()
}

pub fn __eq__(&self, other: &Bound<PyAny>) -> Py<PyAny> {
let py = other.py();
let Ok(other) = other.extract::<Self>() else { return py.NotImplemented() };
(*self == other).into_py(py)
}

pub fn __hash__(&self) -> isize {
*self as isize
}
}

// This must be kept up-to-date with `StandardGate` when adding or removing
Expand Down
32 changes: 8 additions & 24 deletions qiskit/qasm3/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,39 +456,23 @@ class SubroutineBlock(ProgramBlock):
pass


class QuantumArgument(QuantumDeclaration):
"""
quantumArgument
: 'qreg' Identifier designator? | 'qubit' designator? Identifier
"""


class QuantumGateSignature(ASTNode):
class QuantumGateDefinition(Statement):
"""
quantumGateSignature
: quantumGateName ( LPAREN identifierList? RPAREN )? identifierList
quantumGateDefinition
: 'gate' quantumGateSignature quantumBlock
"""

def __init__(
self,
name: Identifier,
qargList: List[Identifier],
params: Optional[List[Expression]] = None,
params: Tuple[Identifier, ...],
qubits: Tuple[Identifier, ...],
body: QuantumBlock,
):
self.name = name
self.qargList = qargList
self.params = params


class QuantumGateDefinition(Statement):
"""
quantumGateDefinition
: 'gate' quantumGateSignature quantumBlock
"""

def __init__(self, quantumGateSignature: QuantumGateSignature, quantumBlock: QuantumBlock):
self.quantumGateSignature = quantumGateSignature
self.quantumBlock = quantumBlock
self.qubits = qubits
self.body = body


class SubroutineDefinition(Statement):
Expand Down
Loading

0 comments on commit 59fc495

Please sign in to comment.