Conversation
|
👋 Hey there! It looks like the changelog might need an update. Please take a moment to edit the
|
| program = openqasm3.parse(program) | ||
| except (openqasm3.parser.QASM3ParsingError, openpulse.parser.OpenPulseParsingError) as err: | ||
| raise ValidationError(f"Failed to parse the OpenQASM/Openpulse string: {err}") from err | ||
| elif not isinstance(program, openqasm3.ast.Program): |
There was a problem hiding this comment.
Shouldn't we check for both the ast types here i.e. for openqasm3.ast.Program and openpulse.ast.Program?
There was a problem hiding this comment.
I think we don’t need to parse inputs separately; we can simply call openpulse.parser.parse_openpulse() inside calibration functions to handle their statement body.
Suggestion: since openpulse.parse() parses both generic QASM AST's and OpenPulse ASTs, we can replace our current call to openqasm.parse() with openpulse.parse().
| visitor (QasmVisitor): The visitor to accept | ||
| """ | ||
| unrolled_stmt_list = visitor.visit_basic_block(self._statements) | ||
| # print("--------------------------------") |
|
|
||
|
|
||
|
|
||
| # You'll also need these other visitor methods for your visit map: |
| print("Calibration Statement Structure:") | ||
| print("Statement: ", statement) |
| print("Calibration Grammar Declaration Structure:") | ||
| print("Declaration: ", declaration) |
| print("--------------------------------") | ||
| print("Gate name: ", gate_name) | ||
| print("--------------------------------") |
There was a problem hiding this comment.
remove, or move to logging level DEBUG
| print("--------------------------------") | ||
| print("Parsing physical qubits: ", qubits) |
There was a problem hiding this comment.
remove or replace with logger
| print("--------------------------------") | ||
| print("Qubit: ", qubit) | ||
| print("--------------------------------") |
| ) | ||
|
|
||
| print("--------------------------------") | ||
| return physical_qubits |
| print("--------------------------------") | ||
| print("Validating calibration arguments: ", arguments) | ||
| print("--------------------------------") |
There was a problem hiding this comment.
remove or replace with logger
| print("--------------------------------") | ||
| print("Argument: ", arg) | ||
| print("--------------------------------") |
| print("--------------------------------") | ||
| print("Validating calibration body: ", body) | ||
| print("--------------------------------") |
There was a problem hiding this comment.
remove or replace with logger
| print("--------------------------------") | ||
| print("Validating calibration body: ", body) | ||
| print("--------------------------------") |
There was a problem hiding this comment.
remove or replace with logger
| grammar_name = declaration.name | ||
|
|
||
| # Validate supported calibration grammars | ||
| supported_grammars = {"openpulse"} # Add more as needed |
There was a problem hiding this comment.
Better to make this a constant and move to maps sub-package
| ) | ||
|
|
||
| try: | ||
| physical_qubit_id = int(qubit_name[1:]) |
There was a problem hiding this comment.
Please check that the qubit index is >=0 here AND , if device_qubits are specified (see PR #222 for reference), within the range of the total number of the qubits present on the device for which this program is intended
There was a problem hiding this comment.
Moreover, as stated above, not all args will be having a prefixed $ sign. Will need to treat those as an identifier then****
| print("--------------------------------") | ||
| return physical_qubits | ||
|
|
||
| def _validate_calibration_arguments(self, arguments: list, gate_name: str, definition: pulse_ast.CalibrationDefinition) -> None: |
There was a problem hiding this comment.
Should be refactored to the Qasm3Validator module
| ) | ||
| seen_qubits.add(qubit_name) | ||
|
|
||
| if not qubit_name.startswith('$'): |
There was a problem hiding this comment.
We can't assume that the qubit arguments will only be composed of physical qubits. If you see the example -
defcal rz(angle[20] theta) q { ... }
// we've defined ``rz`` on arbitrary physical qubits, so we can do:
rz(3.14) $0;
rz(3.14) $1;the defcals blocks can also be defined for identifiers , meaning that for all physical qubits, we are to follow the given defcal body.
| 'DurationType': 64, 'ComplexType': 128 | ||
| }.get(type_name, 32) | ||
|
|
||
| def _validate_openpulse_declaration_type(self, stmt, gate_name: str, definition) -> None: |
There was a problem hiding this comment.
refactor the the Qasm3Validator
| span=definition.span, | ||
| ) | ||
|
|
||
| def _basic_pulse_declaration_validation(self, stmt, gate_name: str, definition) -> None: |
There was a problem hiding this comment.
Again, refactor to the Qasm3Validator module
| ) | ||
| self._add_var_in_scope(variable) | ||
|
|
||
| def _validate_openpulse_function_call(self, stmt, gate_name: str, definition) -> None: |
There was a problem hiding this comment.
Refactor to the Qasm3Validator module
| if hasattr(stmt, 'expression') and hasattr(stmt.expression, 'name'): | ||
| func_name = stmt.expression.name.name | ||
|
|
||
| openpulse_functions = { |
There was a problem hiding this comment.
define in the maps/pulse.py module
| def _validate_openpulse_declaration_type(self, stmt, gate_name: str, definition) -> None: | ||
| """Validate that declaration uses valid openpulse types.""" | ||
| type_name = type(stmt.type).__name__ | ||
| valid_types = {'WaveformType', 'FrameType', 'PortType', 'IntType', 'FloatType', 'AngleType', 'DurationType'} |
There was a problem hiding this comment.
define in the maps/pulse.py module
| print("Validating calibration body: ", body) | ||
| print("--------------------------------") | ||
| for stmt in body: | ||
| self._validate_calibration_statement_dispatch(stmt, gate_name, definition) |
There was a problem hiding this comment.
Let's handle exceptions here. We can extract the type name and catch the raised exceptions instead of duplicating the raising in the dispatch method
| def _get_calibration_arg_size(self, arg_type) -> int: | ||
| """Get size for calibration argument type.""" | ||
| type_name = type(arg_type).__name__ | ||
| return { |
There was a problem hiding this comment.
Move the dict to maps/pulse.py and directly use the .get method on it. Will ensure that we're not redefining it again and again during fn call.
| pip install pyqasm | ||
| ``` | ||
|
|
||
| ### Optional Dependencies |
There was a problem hiding this comment.
Please remove these README changes, I have already consolidated these extra installs under 1 head.
There was a problem hiding this comment.
Hi @arunjmoorthy , thank you for the great work! I have given some comments regarding the refactor of code and about adding more validations.
Also, please add unit tests for the openpulse grammar. I know that there are a LOT of cases, but we'll need to cover all of them in order to achieve our goal of full QASM coverage!
@vinayswamik do have a look at the PR, maybe you guys can collaborate on this?
Summary of changes
This is a draft PR. This does not solve all of the issues in issue 183. Look at the bottom of the visitor.py file. There, some of the functions are implemented to parse the defcal block, which has several restrictions. Additionally, one openpulse test example file has been added to help with iterating and testing.