Open 1ucian0 opened 3 years ago
@jwoehr Can you comment on this issue so that I can assign you? Please also work with your mentor to refine the project, define scope and deliverables and update the project description in this issue.
@1ucian0 and I met on this today.
Our goal in the context of the mentor experience is to separate QASM into its own module and unify its programmatic usage around a functional syntax.
We will implement this with QASM2 and lay the groundwork for QASM3 to inherit this architecture.
Quick notes from our shared document:
from qiskit.qasm2 import dump, load
dump(QuantumCircuitObject) -> str # i.e., a qasm2 string
load
either qasm2 source or frozen circuit per QPY https://github.com/Qiskit/qiskit-terra/pull/5578 gate.qasm()
. but allow a custom gate._qasm()
for special casesgate.qasm()
into import/export functional interface
gate._qasm()
special case before defaulting to its own methodsgate.qasm()
syntax by delegation to the new functional interfaceWe also discussed the following tangential QASM desideratum:
Next I will dig up my work on the functional API as a module of Terra from last year or recreate it from what we left in 1ucian0 /qiskit-openqasm2 (which was qasm2 as a package) and check it into the unified_qasm_api
branch.
Have recreated the qasm2
module in the unified_qasm_api
in the jwoehr /qiskit-terra
fork.
It passes tox
.
Updated the functional interface for export()
in the jwoehr/qiskit-terra
fork to match the code now found in QuantumCircuit
@1ucian0 and @jwoehr met today:
qasm2
module
functions.py
qasm2
vs qasm
)QuantumCircuit
and deprecate the qasm methods in that class in favor of the functional interface
load()
and export()
share core code or are totally separate operationsQuantumCircuit
to the new qasm2
moduleIn unified_qasm_api
branch of jwoehr /qiskit-terra
Added a release note. @1ucian0 , if we are going to PR before proceeding to change the .qasm() / ._qasm() logic of individual operators, now is the time to do it. Or if you want me to proceed to that further stage of development, please let me know.
Awesome work @jwoehr Thanks for sharing all the updates for the project. Looks really exciting!
Thanks for kind words. Just having fun :)
Created PR #6053
Next idea:
def _circuit_from_qasm(qasm):
# pylint: disable=cyclic-import
from qiskit.converters import ast_to_dag
from qiskit.converters import dag_to_circuit
ast = qasm.parse()
dag = ast_to_dag(ast)
circuit = ast_to_circuit(ast)
assert circuit == dag_to_circuit(dag)
return dag_to_circuit(dag)
Our discussion today was ideas to tidy up Qasm2 awaiting advent of Qasm3.
Meeting today with Dr. Bello
QuantumCircuit
assembly of openqasm2grammar
subdir of qiskit-terra/qiskit/qasm2
contain grammar and all generated filesantlr4
to pip requirements for qiskit-terraload()
and export()
to load()
and dump()
. Branched unified_qasm_api branch
to grammar branch
Meeting today with Dr. Bello
QuantumCircuit
objects need to output themselves as OpenQASM 3.This brings some facets of the implementation to the forefront.
qelib1.inc
is not actually used by the OpenQASM 2 translator.qelib1.inc
is returned to its original specification and the accretions are moved to qiskit/qasm/libs/standard_gates.inc
load()
and export()
[or dump()
]] in the future going to:
QuantumCircuit
for the standard gates?QuantumCircuit
?QuantumCircuit
is responsible to know its own qasm representation. There is some interest in modifying this arrangement to make things simpler for gate authors.QuantumCircuit
that would make load and export operations more mutually symmetrical?As our mentorship midterm checkpoint presentation will show, we have a grammar
branch of qiskit.qasm2
that implements OpenQASM 2 ANTLR parsing using essentially the new OpenQASM 3 grammar. It's not a long journey from that to a translator using this new grammar. At present, the intention is to continue work on Qiskit/qiskit-terra#6089 using the OpenQASM 3 grammar, ignoring or raising if features unsupported by OpenQASM 2 are invoked. If in the future the OpenQASM 3 grammar diverges too much from being a pure superset of OpenQASM 2 we will part ways with that definition.
Meeting with Dr. Bello 2021-04-09
qelib1.inc
and/or from any other file include
ed by the programmer and move to regularize this in the new qasm2 code translator.
include
actually operates could break test cases if formal definitions found in qelib1.inc
and/or the new standard_gates.inc
have been superseded by inline code in the Qiskit libraries.// @
) for instance.Notes before meeting with Dr. Bello scheduled for 2021-04-16:
skip
QuantumCircuit
Meeting 2021-04-16 with Dr. Bello
\\@
metacommentsoh la la, this is interesting!
(just commenting here so that I can receive the notifications and learn a bit as well ^^)
since you're rewriting the qasm parser can you include a tiny fix update for #6169?
Maybe a possible use for PRAGMA
s? Something like:
OPENQASM 2.0;
include "qelib1.inc";
//@ QISKIT_DEFINITION initialize(x0, x1, x2, x3) q0, q1;
opaque initialize2(x0, x1, x2, x3) q0, q1;
//@ QISKIT_DEFINITION initialize(x0, x1) q0;
opaque initialize1(x0, x1) q0;
qreg q[3];
initialize2(0,1,0,0) q[0],q[1];
initialize1(0,1) q[2];
where //@ QISKIT_DEFINITION
means "take the qiskit definition instead".
Meeting 2021-04-16 with Dr. Bello
\\@
metacommentsThe qasm2 file:
// yiqing_5.qasm
// This is a version of yiqing_simple declared as 5 qubits
// so that it will run on the QuantumInspire Starmon-5 QPU
OPENQASM 2.0;
include "qelib1.inc";
qreg q[5];
creg c[5];
h q[0];
h q[1];
h q[2];
// h q[3];
// h q[4];
measure q[0] -> c[0];
measure q[1] -> c[1];
measure q[2] -> c[2];
// measure q[3] -> c[3];
// measure q[4] -> c[4];
... using the new antlr4 stuff yields an AST as follows:
{'CSect': [None,
None,
{'ctx': <qiskit.qasm2.grammar.qasm2Parser.qasm2Parser.QuantumDeclarationContext object at 0x7f28f1979890>,
'filenum': 0,
'index_identifier_list': ['q[5]'],
'linenum': 6,
'quantum_type': 'qreg'},
{'bit_type': 'creg',
'ctx': <qiskit.qasm2.grammar.qasm2Parser.qasm2Parser.ClassicalDeclarationContext object at 0x7f28f1942970>,
'filenum': 0,
'index_identifier_list': ['c[5]'],
'linenum': 7},
{'ctx': <qiskit.qasm2.grammar.qasm2Parser.qasm2Parser.SubroutineCallContext object at 0x7f28f1955510>,
'expression_list': ['q[0]'],
'filenum': 0,
'linenum': 8,
'op': 'h'},
{'ctx': <qiskit.qasm2.grammar.qasm2Parser.qasm2Parser.SubroutineCallContext object at 0x7f28f1921040>,
'expression_list': ['q[1]'],
'filenum': 0,
'linenum': 9,
'op': 'h'},
{'ctx': <qiskit.qasm2.grammar.qasm2Parser.qasm2Parser.SubroutineCallContext object at 0x7f28f19215f0>,
'expression_list': ['q[2]'],
'filenum': 0,
'linenum': 10,
'op': 'h'},
{'ctx': <qiskit.qasm2.grammar.qasm2Parser.qasm2Parser.QuantumMeasurementAssignmentContext object at 0x7f28f1921c80>,
'filenum': 0,
'index_identifier_list': ['q[0]', 'c[0]'],
'linenum': 13},
{'ctx': <qiskit.qasm2.grammar.qasm2Parser.qasm2Parser.QuantumMeasurementAssignmentContext object at 0x7f28f192e2e0>,
'filenum': 0,
'index_identifier_list': ['q[1]', 'c[1]'],
'linenum': 14},
{'ctx': <qiskit.qasm2.grammar.qasm2Parser.qasm2Parser.QuantumMeasurementAssignmentContext object at 0x7f28f192e900>,
'filenum': 0,
'index_identifier_list': ['q[2]', 'c[2]'],
'linenum': 15}],
... etc ... GSect SSect TSect not shown above.
(The None, None
at the head of the CSect is an"unfinished stuff" bug)
I'm also ready to propose about metacomments. Good example from Slack user requirement:
\\@ parameters #P1 #P2 ...
Qasm3 already uses @
and $
(too much 😄). So I'm going to suggest #
for params.
parameters={'P1': 1234, 'P2': np.pi}
#P1
or #P2
in the Qasm code gets substituted according to the kwarg.Qasm2Loader
which will expose methods employed by the functional interface load().Qasm2Listener
and Qasm2Loader
.(The
None, None
at the head of the CSect is an"unfinished stuff" bug)
Fixed
\\@ parameters #P1 #P2
OPENQASM 2.1 <-- maybe a good reason to increment this minor?
...
u1(#P1) q[0]; <-- does pytket support #P1 or P1 ?
OPENQASM 2.0;
include "qelib1.inc";
qreg q[1];
//@ QISKIT_DEFINITION HGate;
h q[0];
OPENQASM 2.0;
include "qelib1.inc";
qreg q[1];
//@ qelib1.inc;
h q[0];
load(include_path=[<custom location>, <default location>])
Qasm2Loader.ast_qasm_str()
Qasm2Loader.ast_qasm_file()
/@
to avoid modifying extant sections of qasm antlr4 grammarinitialize
/initialize2
use case raised by Dr. Bello earlier in this issue.qelib1.inc
.black
to format code to avoid merge weirdness.QuantumCircuit
Gate
QuantumCircuit
Qasm2Translator
class
expression_list
fieldparameter_list
fieldtarget_list
fieldQasm2Ast.find_latest_gatedef()
Qasm2Listener
accordinglyopaque
QuantumCircuit
op lookup can't be directly from __dict__
, need lookup tablegrammar
branch from its branch parent unified_qasm_api
to avoid merge conflicts.Qasm2Listener
accordinglyQasm2Translator.apply_standard_gate()
Examined how to bind parameter expressions at translate time.
Example code:
from qiskit.circuit import Parameter, QuantumCircuit
phi = Parameter("phi")
jax = QuantumCircuit(2, name='jax')
jax.u1(phi/2, 1)
binded_jax = jax.bind_parameters({phi:8})
circuit = QuantumCircuit(3)
circuit.append(binded_jax.to_gate(), [1, 2])
circuit.draw()
circuit.decompose().draw()
import numpy as np
binded_jax = jax.bind_parameters({phi:np.pi})
circuit.append(binded_jax.to_gate(), [1, 2])
Qasm2Listener
accordingly
>>> qc.draw()
┌───────────┐┌────────────────────┐
q_0: ┤ U3(1,2,3) ├┤ U3(2.1,3.2,4.3346) ├
└───────────┘└────────────────────┘
q_1: ───────────────────────────────────
c: 2/═══════════════════════════════════
qc.decompose().draw() ┌──────────┐┌───────────────────┐ q_0: ┤ U(1,2,3) ├┤ U(2.1,3.2,4.3346) ├ └──────────┘└───────────────────┘ q_1: ─────────────────────────────────
c: 2/═════════════════════════════════
- AST for Gate definitions better formulated, example:
{'filenum': 1, 'linenum': 63, 'ctx': <qiskit.qasm2.grammar.qasm2Parser.qasm2Parser.QuantumGateDefinitionContext object at 0x7fd14b778430>, 'op': 'ch', 'declaration': ['ch', 'a,b'], 'parameter_list': [], 'target_list': ['a', 'b'], 'definition': [{'op': 'h', 'parameter_list': [], 'target_list': ['b']}, {'op': 'sdg', 'parameter_list': [], 'target_list': ['b']}, {'op': 'cx', 'parameter_list': [], 'target_list': ['a', 'b']}, {'op': 'h', 'parameter_list': [], 'target_list': ['b']}, {'op': 't', 'parameter_list': [], 'target_list': ['b']}, {'op': 'cx', 'parameter_list': [], 'target_list': ['a', 'b']}, {'op': 't', 'parameter_list': [], 'target_list': ['b']}, {'op': 'h', 'parameter_list': [], 'target_list': ['b']}, {'op': 's', 'parameter_list': [], 'target_list': ['b']}, {'op': 'x', 'parameter_list': [], 'target_list': ['b']}, {'op': 's', 'parameter_list': [], 'target_list': ['a']}], 'gate': None}, {'filenum': 1, 'linenum': 89, 'ctx': <qiskit.qasm2.grammar.qasm2Parser.qasm2Parser.QuantumGateDefinitionContext object at 0x7fd14b77ff90>, 'op': 'crx', 'declaration': ['crx', '(', 'lambda', ')', 'a,b'], 'parameter_list': ['lambda'], 'target_list': ['a', 'b'], 'definition': [{'op': 'u1', 'parameter_list': ['pi/2'], 'target_list': ['b']}, {'op': 'cx', 'parameter_list': [], 'target_list': ['a', 'b']}, {'op': 'u3', 'parameter_list': ['-lambda/2', '0', '0'], 'target_list': ['b']}, {'op': 'cx', 'parameter_list': [], 'target_list': ['a', 'b']}, {'op': 'u3', 'parameter_list': ['lambda/2', '-pi/2', '0'], 'target_list': ['b']}], 'gate': None}, {'filenum': 1, 'linenum': 7, 'ctx': <qiskit.qasm2.grammar.qasm2Parser.qasm2Parser.QuantumGateDefinitionContext object at 0x7fd14b7eaeb0>, 'op': 'u3', 'declaration': ['u3', '(', 'theta,phi,lambda', ')', 'q'], 'parameter_list': ['theta', 'phi', 'lambda'], 'target_list': ['q'], 'definition': [{'op': 'U', 'parameter_list': ['theta', 'phi', 'lambda'], 'target_list': ['q']}], 'gate': None}
- Work on `gate_def_for_gate()` and `gate_def_to_gate()`
- Made [slide deck](https://docs.google.com/presentation/d/1_WFLMHdCy0dZpOS0QFPRSIhPBEXSjTdow6IiAc943Z4/edit?usp=sharing) and [video](https://drive.google.com/file/d/1qjK7cw3YZY8PT6kR0a-5I3HlS6s7lkBa/view?usp=sharing) for mentorship final showcase
to the point. Looks very nice 😄
The new OpenQASM 2 translator based on the OpenQASM 3 grammar works more or less completely now.
OPENQASM 2.0;
include "qelib1.inc";
qreg q[3];
creg c[3];
u3(1,1.5707963267948966,3) q[0];
u3(2.1,3.2,4.33456) q[0];
u3(pi/2, 2+3, pi) q[0];
cx q[0], q[1];
barrier q;
barrier q[0];
barrier q[1];
barrier q[1];
barrier q[0], q[1];
measure q[0] -> c[0];
measure q[1] -> c[1];
measure q[0:2] -> c[0:2];
measure q -> c;
┌─────────────┐┌────────────────────┐┌─────────────┐ ░ ░ ░ ┌─┐ ┌─┐ ┌─┐
q_0: ┤ U3(1,π/2,3) ├┤ U3(2.1,3.2,4.3346) ├┤ U3(π/2,5,π) ├──■───░──░─────░─┤M├───┤M├───┤M├───
└─────────────┘└────────────────────┘└─────────────┘┌─┴─┐ ░ ░ ░ ░ └╥┘┌─┐└╥┘┌─┐└╥┘┌─┐
q_1: ────────────────────────────────────────────────────┤ X ├─░──░──░──░──╫─┤M├─╫─┤M├─╫─┤M├
└───┘ ░ ┌─┐ ░ ░ ║ └╥┘ ║ └╥┘ ║ └╥┘
q_2: ──────────────────────────────────────────────────────────░─┤M├───────╫──╫──╫──╫──╫──╫─
░ └╥┘ ║ ║ ║ ║ ║ ║
c: 3/═════════════════════════════════════════════════════════════╩════════╩══╩══╩══╩══╩══╩═
2 0 1 0 1 0 1
Description
There are several way to import and export circuit to and from Qiskit, being OpenQASM2 the most popular one. However, in order to improve interoperability with 3rd parties, we need to organize that a bit. The first stage is to move all the qasm2-related code we have around into a
qiskit.qasm2
module. After that, we can take other serializer like https://github.com/jwoehr/nuqasm2 or https://github.com/Qiskit/qiskit-terra/pull/5578.Mentor/s
@1ucian0
Type of participant
A good python coder. If you have knowledge on design patterns, even better.
Number of participants
1
Deliverable
A Qiskit PR (or several)