qiskit-advocate / qamp-spring-21

Qiskit advocate mentorship program (QAMP) spring 21 cohort
42 stars 11 forks source link

Unified API to import/export circuits in Qiskit #39

Open 1ucian0 opened 3 years ago

1ucian0 commented 3 years ago

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)

HuangJunye commented 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.

jwoehr commented 3 years ago

@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:

jwoehr commented 3 years ago

We also discussed the following tangential QASM desideratum:

jwoehr commented 3 years ago

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.

jwoehr commented 3 years ago

Have recreated the qasm2 module in the unified_qasm_api in the jwoehr /qiskit-terra fork. It passes tox.

jwoehr commented 3 years ago

Updated the functional interface for export() in the jwoehr/qiskit-terra fork to match the code now found in QuantumCircuit

jwoehr commented 3 years ago

@1ucian0 and @jwoehr met today:

Coding assignment

jwoehr commented 3 years ago

Opened https://github.com/Qiskit/openqasm/pull/162

jwoehr commented 3 years ago

In unified_qasm_api branch of jwoehr /qiskit-terra

jwoehr commented 3 years ago

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.

HuangJunye commented 3 years ago

Awesome work @jwoehr Thanks for sharing all the updates for the project. Looks really exciting!

jwoehr commented 3 years ago

Thanks for kind words. Just having fun :)

jwoehr commented 3 years ago

Created PR #6053

jwoehr commented 3 years ago

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)
jwoehr commented 3 years ago

Our discussion today was ideas to tidy up Qasm2 awaiting advent of Qasm3.

jwoehr commented 3 years ago

Meeting today with Dr. Bello

jwoehr commented 3 years ago

Branched unified_qasm_api branch to grammar branch

jwoehr commented 3 years ago

Meeting today with Dr. Bello

Qiskit QuantumCircuit objects need to output themselves as OpenQASM 3.

This brings some facets of the implementation to the forefront.

Progress in the past week

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.

Plan for coming week

jwoehr commented 3 years ago

Meeting with Dr. Bello 2021-04-09

jwoehr commented 3 years ago

Notes before meeting with Dr. Bello scheduled for 2021-04-16:

jwoehr commented 3 years ago

Meeting 2021-04-16 with Dr. Bello

omarcostahamido commented 3 years ago

oh 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?

1ucian0 commented 3 years ago

Maybe a possible use for PRAGMAs? 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".

jwoehr commented 3 years ago

Meeting 2021-04-16 with Dr. Bello

jwoehr commented 3 years ago

Progress up to 2021

The 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)

Qasm 2 Metacomments

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.

My task list

  1. Finish AST code section.
  2. Do AST gate section (then basic AST will be complete).
  3. Create class Qasm2Loader which will expose methods employed by the functional interface load().
  4. Modify grammar to support metacomments.
  5. Implement metacomments in Qasm2Listener and Qasm2Loader.
jwoehr commented 3 years ago

(The None, None at the head of the CSect is an"unfinished stuff" bug)

Fixed

1ucian0 commented 3 years ago
\\@ parameters #P1 #P2
OPENQASM 2.1  <-- maybe a good reason to increment this minor?
...
u1(#P1) q[0];   <-- does pytket support #P1 or P1 ?
1ucian0 commented 3 years ago
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];
1ucian0 commented 3 years ago
load(include_path=[<custom location>, <default location>])
jwoehr commented 3 years ago

Progress for week ending 2021-04-30

  1. Created class Qasm2Loader implementing:
    • Qasm2Loader.ast_qasm_str()
    • Qasm2Loader.ast_qasm_file()
  2. Modified grammar to support metacomments.
    • For now using /@ to avoid modifying extant sections of qasm antlr4 grammar
  3. Implemented metacomments in Qasm2Listener and Qasm2Loader.
    • They appear in the Code section directly before the code statements they precede.
jwoehr commented 3 years ago

Meeting with Dr. Bello 2021-04-30

Jack's task list

jwoehr commented 3 years ago

Meeting with Dr. Bello 2021-05-07

jwoehr commented 3 years ago

Progress week ending 2021-05-07

jwoehr commented 3 years ago

Progress week ending 2021-05-14

jwoehr commented 3 years ago

Meeting 2021-05-14 with Dr. Bello

jwoehr commented 3 years ago

Progress for week ending 2021-05-21

jwoehr commented 3 years ago

Meeting 2021-05-21

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])
jwoehr commented 3 years ago

Progress week ending 2021-06-04

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
omarcostahamido commented 3 years ago

to the point. Looks very nice 😄

jwoehr commented 3 years ago

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