Skip to content

Releases: qBraid/pyqasm

PyQASM 0.5.0

14 Aug 06:13
f2f7e04
Compare
Choose a tag to compare

Release 0.5.0 (August 14, 2025)

Summary

Added

  • A new discussion template for issues in pyqasm (#213)
  • A github workflow for validating CHANGELOG updates in a PR (#214)
  • Added unroll command support in PYQASM CLI with options skipping files, overwriting originals files, and specifying output paths.(#224)
  • Added Duration,Stretch type, Delay and Box support for OPENQASM3 code in pyqasm. (#231)
    Example:
    OPENQASM 3.0;
    include "stdgates.inc";
    qubit[3] q;
    duration t1 = 200dt;
    duration t2 = 300ns;
    stretch s1;
    delay[t1] q[0];
    delay[t2] q[1];
    delay[s1] q[0], q[2];
    box [t2] {
      h q[0];
      cx q[0], q[1];
      delay[100ns] q[2];
    }
  • Added a new QasmModule.compare method to compare two QASM modules, providing a detailed report of differences in gates, qubits, and measurements. This method is useful for comparing two identifying differences in QASM programs, their structure and operations. (#233)
  • Added .github/copilot-instructions.md to the repository to document coding standards and design principles for pyqasm. This file provides detailed guidance on documentation, static typing, formatting, error handling, and adherence to the QASM specification for all code contributions. (#234)
  • Added support for custom include statements in OPENQASM3 code in pyqasm. This allows users to include custom files or libraries in their QASM programs, enhancing modularity and reusability of code. (#236)
  • Added support for Angle,extern and Complex type in OPENQASM3 code in pyqasm. (#239)
    Example:
    OPENQASM 3.0;
    include "stdgates.inc";
    angle[8] ang1;
    ang1 = 9 * (pi / 8);
    angle[8] ang1 = 7 * (pi / 8);
    angle[8] ang3 = ang1 + ang2;
    
    complex c1 = -2.5 - 3.5im;
    const complex c2 = 2.0+arccos(π/2) + (3.1 * 5.5im);
    const complex c12 = c1 * c2;
    
    float a = 1.0;
    int b = 2;
    extern func1(float, int) -> bit;
    bit c = 2 * func1(a, b);
    bit fc = -func1(a, b);
    
    bit[4] bd = "0101";
    extern func6(bit[4]) -> bit[4];
    bit[4] be1 = func6(bd);

Improved / Modified

  • Added slots=True parameter to the data classes in elements.py to improve memory efficiency (#218)
  • Updated the documentation to include core features in the README (#219)
  • Added support to device qubit resgister consolidation.(#222)
  • Updated the scoping of variables in QasmVisitor using a ScopeManager. This change is introduced to ensure that the QasmVisitor and the PulseVisitor can share the same ScopeManager instance, allowing for consistent variable scoping across different visitors. No change in the user API is expected. (#232)
  • Enhance function call handling by adding support for nested functions. This change allows for more complex function definitions and calls, enabling better modularity and reusability of code within QASM programs. (#245)

Deprecated

Removed

Fixed

  • Fixed multiple axes error in circuit visualization of decomposable gates in draw method. (#209)
  • Fixed depth calculation for decomposable gates by computing depth of each constituent quantum gate.(#211)
  • Optimized statement copying in _visit_function_call with shallow-copy fallback to deepcopy and added max_loop_iters loop‐limit check in for loops.(#223)

Dependencies

  • Add pillow<11.3.0 dependency for test and visualization to avoid CI errors in Linux builds (#226)
  • Added tabulate to the testing dependencies to support new comparison table tests. (#216)
  • Update docutils requirement from <0.22 to <0.23 (#241)
  • Bumps actions/download-artifact version from 4 to 5 (#243)

New Contributors

Full Changelog: v0.4.0...v0.5.0

PyQASM 0.4.0

17 Jun 06:03
c27b69e
Compare
Choose a tag to compare

Release 0.4.0 (June 17, 2025)

Summary

Added

  • Added the pulse extra dependency to the pyproject.toml file, which includes the openpulse package. This allows users to install pulse-related functionality when needed. (#195)
  • Added support for unrolling while loops with compile time condition evaluation. Users can now use unroll on while loops which do not have conditions depending on quantum measurements. (#206) Eg. -
import pyqasm 

qasm_str = """
    OPENQASM 3.0;
    qubit[4] q;
    int i = 0;
    while (i < 3) {
        h q[i];
        cx q[i], q[i+1];
        i += 1;
    }

    """
result = pyqasm.loads(qasm_str)
result.unroll()
print(result)

# **Output**

# OPENQASM 3.0;
# qubit[4] q;
# h q[0];
# cx q[0], q[1];
# h q[1];
# cx q[1], q[2];
# h q[2];
# cx q[2], q[3];

Improved / Modified

  • Refactored analyze_classical_indices method to use @staticmethod instead of @classmethod. (#194)
  • Optimized _visit_generic_gate_operation in QasmVisitor class by using shallow copy instead of deep copy for better performance when processing gate operations. (#180)

Deprecated

Removed

Fixed

  • Fixed the way how depth is calculated when external gates are defined with unrolling a QASM module. (#198)
  • Added separate depth calculation for gates inside branching statements. (#200)
    • Example:
    OPENQASM 3.0;
    include "stdgates.inc";
    qubit[4] q;
    bit[4] c;
    bit[4] c0;
    if (c[0]){
      x q[0];
      h q[0]
      }
    else {
      h q[1];
    }
    Depth = 1
    
    • Previously, each gate inside an if/else block would advance only its own wire depth. Now, when any branching statement is encountered, all qubit‐ and clbit‐depths used inside that block are first incremented by one, then set to the maximum of those new values. This ensures the entire conditional block counts as single “depth” increment, rather than letting individual gates within the same branch float ahead independently.
    • In the above snippet, c[0], q[0], and q[1] all jump together to a single new depth for that branch.
  • Added initial support to explicit casting by converting the declarations into implicit casting logic. (#205)

Dependencies

New Contributors

Full Changelog: v0.3.2...v0.4.0

PyQASM 0.3.2

25 Apr 05:45
fbb4fb6
Compare
Choose a tag to compare

Release 0.3.2 (April 25, 2025)

Summary

Added

Improved / Modified

Deprecated

Removed

Fixed

  • Fixed bugs in the PARAMS_OP_SET by adding entries for u1, prx and cphaseshift10 gates. These gates were required to correctly run the tests for qbraid-qir and the qBraid packages. (#176) (#177)

Dependencies

Other

What's Changed

Full Changelog: v0.3.1...v0.3.2

PyQASM 0.3.1

21 Apr 05:49
776e9ef
Compare
Choose a tag to compare

Release 0.3.1 (April 21, 2025)

Summary

Added

  • Added support for conditionally unrolling barrier statements in the unroll method with the unroll_barriers flag. (#166) -
In [1]: import pyqasm

In [2]: qasm_str = """
   ...:     OPENQASM 3.0;
   ...:     include "stdgates.inc";
   ...: 
   ...:     qubit[2] q1;
   ...:     qubit[3] q2;
   ...:     qubit q3;
   ...: 
   ...:     // barriers
   ...:     barrier q1, q2, q3;
   ...:     barrier q2[:3];
   ...:     barrier q3[0];
   ...: """

In [3]: module = pyqasm.loads(qasm_str)

In [4]: module.unroll(unroll_barriers = False)

In [5]: print(module)
OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q1;
qubit[3] q2;
qubit[1] q3;
barrier q1, q2, q3;
barrier q2[:3];
barrier q3[0];
  • Introduced a new environment variable called PYQASM_EXPAND_TRACEBACK. This variable can be set to true / false to enable / disable the expansion of traceback information in the error messages. The default is set as false. (#171) Eg. -

Script -

import pyqasm

qasm = """
    OPENQASM 3;
    include "stdgates.inc";
    qubit[2] q1;
    rx(a) q1;
    """

program = pyqasm.loads(qasm)
program.unroll()

Execution -

>>> python3 test-traceback.py
ERROR:pyqasm: Error at line 5, column 7 in QASM file

 >>>>>> a

ERROR:pyqasm: Error at line 5, column 4 in QASM file

 >>>>>> rx(a) q1[0], q1[1];


pyqasm.exceptions.ValidationError: Undefined identifier 'a' in expression

The above exception was the direct cause of the following exception:

pyqasm.exceptions.ValidationError: Invalid parameter 'a' for gate 'rx'
>>> export PYQASM_EXPAND_TRACEBACK=true
>>> python3 test-traceback.py
ERROR:pyqasm: Error at line 5, column 7 in QASM file

 >>>>>> a

ERROR:pyqasm: Error at line 5, column 4 in QASM file

 >>>>>> rx(a) q1[0], q1[1];


Traceback (most recent call last):
  .....

  File "/Users/thegupta/Desktop/qBraid/repos/pyqasm/src/pyqasm/expressions.py", line 69, in _check_var_in_scope
    raise_qasm3_error(
  File "/Users/thegupta/Desktop/qBraid/repos/pyqasm/src/pyqasm/exceptions.py", line 103, in raise_qasm3_error
    raise err_type(message)

pyqasm.exceptions.ValidationError: Undefined identifier 'a' in expression

The above exception was the direct cause of the following exception:


Traceback (most recent call last):
  .....

  File "/Users/thegupta/Desktop/qBraid/repos/pyqasm/src/pyqasm/visitor.py", line 2208, in visit_basic_block
    result.extend(self.visit_statement(stmt))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/thegupta/Desktop/qBraid/repos/pyqasm/src/pyqasm/visitor.py", line 2188, in visit_statement
    result.extend(visitor_function(statement))  # type: ignore[operator]
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/thegupta/Desktop/qBraid/repos/pyqasm/src/pyqasm/visitor.py", line 1201, in _visit_generic_gate_operation
    result.extend(self._visit_basic_gate_operation(operation, inverse_value, ctrls))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/thegupta/Desktop/qBraid/repos/pyqasm/src/pyqasm/visitor.py", line 820, in _visit_basic_gate_operation
    op_parameters = self._get_op_parameters(operation)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/thegupta/Desktop/qBraid/repos/pyqasm/src/pyqasm/visitor.py", line 660, in _get_op_parameters
    raise_qasm3_error(
  File "/Users/thegupta/Desktop/qBraid/repos/pyqasm/src/pyqasm/exceptions.py", line 102, in raise_qasm3_error
    raise err_type(message) from raised_from

pyqasm.exceptions.ValidationError: Invalid parameter 'a' for gate 'rx'

Improved / Modified

  • Improved the error messages for the parameter mismatch errors in basic quantum gates (#169). Following error is raised on parameter count mismatch -
In [1]: import pyqasm
   ...: 
   ...: qasm = """
   ...: OPENQASM 3;
   ...: include "stdgates.inc";
   ...: qubit[2] q;
   ...: rx(0.5, 1) q[1];
   ...: """
   ...: program = pyqasm.loads(qasm)
   ...: program.validate()

......
ValidationError: Expected 1 parameter for gate 'rx', but got 2  
  • Enhanced the verbosity and clarity of pyqasm validation error messages. The new error format logs the line and column number of the error, the line where the error occurred, and the specific error message, making it easier to identify and fix issues in the QASM code. (#171) Eg. -
import pyqasm

qasm = """
    OPENQASM 3;
    include "stdgates.inc";
    qubit[2] q1;
    rx(a) q1;
    """

program = pyqasm.loads(qasm)
program.unroll()
ERROR:pyqasm: Error at line 5, column 7 in QASM file

 >>>>>> a

ERROR:pyqasm: Error at line 5, column 4 in QASM file

 >>>>>> rx(a) q1[0], q1[1];


pyqasm.exceptions.ValidationError: Undefined identifier 'a' in expression

The above exception was the direct cause of the following exception:

pyqasm.exceptions.ValidationError: Invalid parameter 'a' for gate 'rx'

Deprecated

Removed

  • Removed the dependency on Union for typing by replacing it with | (#170).

Fixed

  • Resolved the inconsistency in pyqasm.printer.draw and pyqasm.printer.mpl_draw behaviour for multiple function calls. See issue #165 for bug details. (#168)

Dependencies

PRs Merged

Full Changelog: v0.3.0...v0.3.1

PyQASM 0.3.0

18 Mar 16:35
28c4140
Compare
Choose a tag to compare

Release 0.3.0 (Mar 18, 2025)

Summary

Added

  • Added logic to bump-version.yml workflow that automatically updates CITATION.cff upon new release (#147)
  • Added pyqasm.draw() function that draws quantum circuit (#122):
from pyqasm import draw

qasm = """
OPENQASM 3.0;
include "stdgates.inc";

qubit[3] q;
bit[3] b;

h q[0];
z q[1];
rz(pi/1.1) q[0];
cx q[0], q[1];
swap q[0], q[1];
ccx q[0], q[1], q[2];
b = measure q;
"""

draw(qasm, output='mpl')

Screenshot 2025-03-17 at 2 23 14 PM

- Currently, only the mpl (matplotlib) output format is supported.

- Use draw(..., idle_wires=False) to draw circuit without empty qubit/classical bit registers.

- Save the visualization to a file by specifying output='mpl' and a filename:

draw(..., output='mpl', filename='/path/to/circuit.png')

- The draw method accepts either a str (QASM source) or a QasmModule. The following are equivalent:

from pyqasm import loads, draw
from pyqasm.printer import mpl_draw

module = loads(qasm_str)

draw(module, output='mpl')
draw(qasm_str, output='mpl')

draw(module)
draw(qasm_str)

Fixed

  • Fixed bug in release workflow(s) that caused discrepancy between pyqasm.__version__ and importlib.metadata.version (#147)
  • Fixed a bug in broadcast operation for duplicate qubits so that the following -
OPENQASM 3.0;
include "stdgates.inc";
qubit[3] q;
qubit[2] q2;
cx q[0], q[1], q[1], q[2];
cx q2, q2;

will unroll correctly to -

OPENQASM 3.0;
include "stdgates.inc";
qubit[3] q;
qubit[2] q2;
// cx q[0], q[1], q[1], q[2];
cx q[0], q[1];
cx q[1], q[2];

// cx q2, q2;
cx q2[0], q2[1];
cx q2[0], q2[1];

The logic for duplicate qubit detection is moved out of the QasmVisitor._get_op_bits into Qasm3Analyzer class and is executed post gate broadcast operation (#155).

Other

  • Updated license from GPL-3.0 to Apache-2.0 (#158)
  • Added GitHub actions for publishing to GitHub pages, and updated docs pages from Readthedocs to GitHub pages links. (#158)

PRs Merged

Full Changelog: v0.2.1...v0.3.0

PyQASM 0.2.1

20 Feb 07:43
b6cb1b4
Compare
Choose a tag to compare

Release 0.2.1 (Feb 20, 2025)

Summary

Added

Added support for standalone measurements that do not store the result in a classical register (#141).

Improved / Modified

Re-wrote the QasmAnalyzer.extract_qasm_version method so that it extracts the program version just by looking at the first non-comment line, instead of parsing the entire program (#140).

Deprecated

Removed

Fixed

Solved version discrepancy in release by ensuring no changes are detected by cibuildhweel post checkout (#142).

Dependencies

New Contributors

Full Changelog: v0.2.0...v0.2.1

PyQASM 0.2.0

14 Feb 11:55
0fd2956
Compare
Choose a tag to compare

Release 0.2.0 (Feb 14, 2025)

Summary

Added

  • Added support for classical declarations with measurement (#120). Usage example -
In [1]: from pyqasm import loads, dumps

In [2]: module = loads(
   ...: """OPENQASM 3.0;
   ...: qubit q;
   ...: bit b = measure q;
   ...: """)

In [3]: module.unroll()

In [4]: dumps(module).splitlines()
Out[4]: ['OPENQASM 3.0;', 'qubit[1] q;', 'bit[1] b;', 'b[0] = measure q[0];']
  • Added support for unrolling multi-bit branching with ==, >=, <=, >, and < (#112). Usage example -
In [1]: from pyqasm import loads

In [2]: module = loads(
   ...: """OPENQASM 3.0;
   ...: include "stdgates.inc";
   ...: qubit[1] q;
   ...: bit[4] c;
   ...: if(c == 3){
   ...:     h q[0];
   ...: }
   ...: """)

In [3]: module.unroll()

In [4]: dumps(module)
OPENQASM 3.0;
include "stdgates.inc";
qubit[1] q;
bit[4] c;
if (c[0] == false) {
  if (c[1] == false) {
    if (c[2] == true) {
      if (c[3] == true) {
        h q[0];
      }
    }
  }
}
  • Add formatting check for Unix style line endings i.e. \n. For any other line endings, errors are raised. (#130)
  • Add rebase method to the QasmModule. Users now have the ability to rebase the quantum programs to any of the available pyqasm.elements.BasisSet (#123). Usage example -
In [9] : import pyqasm

In [10]: qasm_input = """ OPENQASM 3.0;
    ...: include "stdgates.inc";
    ...: qubit[2] q;
    ...: bit[2] c;
    ...: 
    ...: h q;
    ...: x q;
    ...: cz q[0], q[1];
    ...: 
    ...: c = measure q; 
    ...: """

In [11]: module = pyqasm.loads(qasm_input)

In [12]: from pyqasm.elements import BasisSet

In [13]: module.rebase(target_basis_set=BasisSet.ROTATIONAL_CX)
Out[13]: <pyqasm.modules.qasm3.Qasm3Module at 0x103744e10>

In [14]: print(pyqasm.dumps(module))
OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
bit[2] c;
ry(1.5707963267948966) q[0];
rx(3.141592653589793) q[0];
ry(1.5707963267948966) q[1];
rx(3.141592653589793) q[1];
rx(3.141592653589793) q[0];
rx(3.141592653589793) q[1];
ry(1.5707963267948966) q[1];
rx(3.141592653589793) q[1];
cx q[0], q[1];
ry(1.5707963267948966) q[1];
rx(3.141592653589793) q[1];
c[0] = measure q[0];
c[1] = measure q[1];

Current support for BasisSet.CLIFFORD_T decompositions is limited to non-parameterized gates only.

  • Added .gitattributes file to specify unix-style line endings(\n) for all files (#123)
  • Added support for ctrl modifiers. QASM3 programs with ctrl @ modifiers can now be loaded as QasmModule objects (#121). Usage example -
In [18]: import pyqasm

In [19]: qasm3_string = """
    ...:     OPENQASM 3.0;
    ...:     include "stdgates.inc";
    ...:     qubit[3] q;
    ...:     gate custom a, b, c {
    ...:         ctrl @ x a, b;
    ...:         ctrl(2) @ x a, b, c;
    ...:     }
    ...:     custom q[0], q[1], q[2];
    ...:     """

In [20]: module = pyqasm.loads(qasm3_string)

In [21]: module.unroll()

In [22]: print(pyqasm.dumps(module))
OPENQASM 3.0;
include "stdgates.inc";
qubit[3] q;
cx q[0], q[1];
ccx q[0], q[1], q[2];

Improved / Modified

  • Bumped qBraid-CLI dep in tox.ini to fix qbraid headers command formatting bug (#129)

Deprecated

Removed

  • Unix-style line endings check in GitHub actions was removed in lieu of the .gitattributes file (#123)

Fixed

Dependencies

  • Update sphinx-autodoc-typehints requirement from <2.6,>=1.24 to >=1.24,<3.1 (#119)

New Contributors

Full Changelog: v0.1.0...v0.2.0

PyQASM 0.1.0

10 Dec 05:28
d8fc16b
Compare
Choose a tag to compare

Release 0.1.0 (Dec 10, 2024)

Summary

Added

  • Added support for gphase, toffoli, not, c3sx and c4x gates (#86)
  • Added a remove_includes method to QasmModule to remove include statements from the generated QASM code (#100). Usage example -
In [1]: from pyqasm import loads

In [2]: module = loads(
   ...: """OPENQASM 3.0;
   ...: include "stdgates.inc";
   ...: include "random.qasm";
   ...: 
   ...: qubit[2] q;
   ...: h q;
   ...: """)

In [3]: module.remove_includes()
Out[3]: <pyqasm.modules.qasm3.Qasm3Module at 0x10442b190>

In [4]: from pyqasm import dumps

In [5]: dumps(module).splitlines()
Out[5]: ['OPENQASM 3.0;', 'qubit[2] q;', 'h q;']

Improved / Modified

  • Refactored the initialization of QasmModule to remove default include statements. Only user supplied include statements are now added to the generated QASM code (#86)
  • Update the pre-release.yml workflow to multi-platform builds. Added the pre-release version bump to the pre_build.sh script. (#99)

Deprecated

Removed

Fixed

  • Fixed bugs in implementations of gpi2 and prx gates (#86)

Dependencies

Full Changelog:

PyQASM 0.1.0-alpha

28 Nov 08:24
9b0c198
Compare
Choose a tag to compare
PyQASM 0.1.0-alpha Pre-release
Pre-release

Release 0.1.0-alpha (Nov 28, 2024)

Summary

Added

  • Added a dumps and formatted_qasm method to the QasmModule class to allow for the conversion of a QasmModule object to a string representation of the QASM code (#71)
  • Added the populate_idle_qubits method to the QasmModule class to populate idle qubits with an id gate (#72)
  • Added gate definitions for "c3sqrtx", "u1", "rxx", "cu3", "csx", "rccx" , "ch" , "cry", "cp", "cu", "cu1", "rzz" in maps.py (#74)
  • Added support for skipping the unrolling for externally linked gates. The QasmModule.unroll() method now accepts an external_gates parameter which is a list of gate names that should not be unrolled (#59). Usage -
In [30]: import pyqasm

In [31]: qasm_str = """OPENQASM 3.0;
    ...:     include "stdgates.inc";
    ...:     gate custom q1, q2, q3{
    ...:         x q1;
    ...:         y q2;
    ...:         z q3;
    ...:     }
    ...:
    ...:     qubit[4] q;
    ...:     custom q[0], q[1], q[2];
    ...:     cx q[1], q[2];"""

In [32]: module = pyqasm.loads(qasm_str)

In [33]: module.unroll(external_gates= ["custom"])

In [34]: pyqasm.dumps(module).splitlines()
Out[34]:
['OPENQASM 3.0;',
 'include "stdgates.inc";',
 'qubit[4] q;',
 'custom q[0], q[1], q[2];',
 'cx q[1], q[2];']
  • Major Change: Added the load, loads, dump, and dumps functions to the pyqasm module to allow for the loading and dumping of QASM code (#76). Usage -
In [18]: import pyqasm

In [19]: qasm_str = """OPENQASM 3.0;
    ...:     include "stdgates.inc";
    ...:     qreg q1[2];
    ...:     qubit[2] q2;"""

In [20]: module = pyqasm.loads(qasm_str)

In [21]: print(pyqasm.dumps(module))
OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q1;
qubit[2] q2;


In [22]: file_path = "test.qasm"

In [23]: pyqasm.dump(module, file_path)

In [24]: module = pyqasm.load(file_path)

In [25]: print(pyqasm.dumps(module))
OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q1;
qubit[2] q2;
  • Added definitions for various gates in maps.py and tests for qasm formatting functions of the qbraid-sdk (#82, #84)
  • Added pyqasm.accelerate module to hold .pyx files with Cython-based optimizations for computationally intensive functions (#83)
  • Added has_barriers method for checking if a QasmModule object contains barriers (#85)
  • Added pyqasm.cli module with typer integration to enable using pyqasm as a command-line tool (#87)
$ pip install 'pyqasm[cli]'
$ pyqasm --help
Usage: pyqasm [OPTIONS] COMMAND [ARGS]...
$ pyqasm --version
pyqasm/0.1.0a1
$ pyqasm validate tests/cli/resources
tests/cli/resources/invalid1.qasm: error: Index 2 out of range for register of size 1 in qubit [validation]
Found errors in 1 file (checked 3 source files)
$ pyqasm validate tests/cli/resources --skip tests/cli/resources/invalid1.qasm
Success: no issues found in 2 source files

Improved / Modified

  • Changed the __init__ method for the QasmModule class to only accept an openqasm3.ast.Program object as input (#71)
  • Changed DepthNode, QubitDepthNode, ClbitDepthNode, and Variable to dataclasses. __repr__ method is therefore handled automatically and you don't need all of the redundant private / public attribute and setters (#79)
  • Simplified map_qasm_op_to_callable redundant KeyError handling with loop (#79)
  • The load function has been renamed to loads and load is now used to load a QASM file. QasmModule.dumps() has been replaced with __str__ method (#76)
  • Experimental Cython integration: (#83)
    • Migrated pyqasm.linalg._kronecker_factor to pyqasm.linalg_cy with ~60% speedup
    • Migrated pyqasm.linalg._so4_to_so2() to to pyqasm.linalg_cy with ~5% speedup
  • Changed source code directory from ./pyqasm to ./src/pyqasm to prevents conflicts between the local source directory and the installed package in site-packages, ensuring Python's module resolution prioritizes the correct version. Required for local testing with new Cython build step (#83)
  • Updated the build process for pyqasm due to Cython integration. Wheels are now built for each platform and uploaded to PyPI along with the source distributions (#88)

Deprecated

Removed

  • Removed the from_program method from the QasmModule class (#71)
  • QasmModule.formatted_qasm() method has been removed (#76)

Fixed

  • Updated docs custom CSS used for sphinx to make version stable/latest drop-down visible. Previously was set white so blended into background and wasn't visible. (#78)
  • Fixed bug in pyqasm.linalg.so_bidiagonalize() in final dot product order (#83)

Dependencies

New Contributors

Full Changelog: v0.0.3...v0.1.0-alpha

PyQASM 0.0.3

06 Nov 13:34
9a9000f
Compare
Choose a tag to compare

Release 0.0.3 (Nov 6, 2024)

Summary

Added

  • Dependabot configuration file (#37)
  • Added support for QASM2 program validation and unrolling (#46)
  • Added better typing to linalg module + some tests (#47)
  • Added a remove_idle_qubits method to the QasmModule class which can be used to remove idle qubits from a quantum program (#58). Usage is as follows -
In [3]: import pyqasm
   ...: qasm_str = """OPENQASM 3.0;
   ...:      gate custom q1, q2, q3{
   ...:          x q1;
   ...:          y q2;
   ...:          z q3;
   ...:      }
   ...:      qreg q1[2];
   ...:      qubit[2] q2;
   ...:      qubit[3] q3;
   ...:      qubit q4;
   ...:      qubit[5]   q5;
   ...:
   ...:      x q1[0];
   ...:      y q2[1];
   ...:      z q3;"""
   ...: module = pyqasm.load(qasm_str)
   ...: module.validate()
   ...:

In [4]: module.num_qubits
Out[4]: 13

In [5]: module.remove_idle_qubits()
Out[5]: <pyqasm.modules.Qasm3Module at 0x1052364b0>

In [6]: module.num_qubits
Out[6]: 5

In [7]: module.unrolled_qasm.splitlines()
Out[7]:
['OPENQASM 3.0;',
 'include "stdgates.inc";',
 'qubit[1] q1;',
 'qubit[1] q2;',
 'qubit[3] q3;',
 'x q1[0];',
 'y q2[0];',
 'z q3[0];',
 'z q3[1];',
 'z q3[2];']
  • Implemented the reverse_qubit_order method to the QasmModule class which can be used to reverse the order of qubits in a quantum program (#60). Usage is as follows -
In [3]: import pyqasm

In [4]: qasm3_str = """
   ...:     OPENQASM 3.0;
   ...:     include "stdgates.inc";
   ...:     qubit[2] q;
   ...:     qubit[4] q2;
   ...:     qubit q3;
   ...:     bit[1] c;
   ...:
   ...:     cnot q[0], q[1];
   ...:     cnot q2[0], q2[1];
   ...:     x q2[3];
   ...:     cnot q2[0], q2[2];
   ...:     x q3;
   ...:     c[0] = measure q2[0];
   ...:     """

In [5]: module = pyqasm.load(qasm3_str)

In [6]: module.reverse_qubit_order()
Out[6]: <pyqasm.modules.Qasm3Module at 0x105bc9ac0>

In [7]: module.unrolled_qasm.splitlines()
Out[7]:
['OPENQASM 3.0;',
 'include "stdgates.inc";',
 'qubit[2] q;',
 'qubit[4] q2;',
 'qubit[1] q3;',
 'bit[1] c;',
 'cx q[1], q[0];',
 'cx q2[3], q2[2];',
 'x q2[0];',
 'cx q2[3], q2[1];',
 'x q3[0];',
 'c[0] = measure q2[3];']
  • Added the to_qasm3() method to the Qasm2Module class which can be used to convert a QASM2 program to QASM3 (#62). Usage is as follows -
In [7]: import pyqasm

In [8]: qasm2_str = """
  ...:      OPENQASM 2.0;
  ...:      include "qelib1.inc";
  ...:      qreg q[2];
  ...:      creg c[2];
  ...:      h q[0];
  ...:      cx q[0], q[1];
  ...:      measure q -> c;
  ...:      """

In [9]: module = pyqasm.load(qasm2_str)

In [10]: module.to_qasm3(as_str = True).splitlines()
Out[10]:
['OPENQASM 3.0;',
'include "stdgates.inc";',
'qubit[2] q;',
'bit[2] c;',
'h q[0];',
'cx q[0], q[1];',
'c = measure q;']

In [11]: qasm3_mod = module.to_qasm3()

In [12]: qasm3_mod
Out[12]: <pyqasm.modules.qasm3.Qasm3Module at 0x107854ad0>

Improved / Modified

  • Improved qubit declaration semantics by adding check for quantum registers being declared as predefined constants (#44)
  • Updated pre-release scripts + workflow (#47)
  • Moved pylint config from pyproject to rcfile, reduced disabled list, and moved disable flags to specific areas where applicable instead of over entire files (#47)
  • Consolidated duplicate code from pyqasm.unroller.py and pyqasm.validate.py into pyqasm.entrypoint.py with new pyqasm.load() function which returns a Qasm3Module (#47)
  • Updated examples in README.md to show outputs and explain in more detail what's happening in each example (#47)
  • Updated the handling of qasm version string by forcing it to be x.0 (#48)
  • Major Update: Changed the API for the unroll and validate functions. Introduced a new load function that returns a QasmModule object, which can be used to then call unroll and validate. Also added methods like remove_measurements, remove_barriers, has_measurements and depth to the QasmModule class (#49). Usage is as follows -
In [1]: import pyqasm

In [2]: qasm_str = """OPENQASM 3.0;
   ...:     gate custom q1, q2, q3{
   ...:         x q1;
   ...:         y q2;
   ...:         z q3;
   ...:     }
   ...:     qreg q1[2];
   ...:     qubit[2] q2;
   ...:     qubit[3] q3;
   ...:     qubit q4;
   ...:     qubit[5]   q5;
   ...:     qreg qr[3];
   ...:
   ...:     x q1[0];
   ...:     y q2[1];
   ...:     z q3;
   ...:
   ...:
   ...:     qubit[3] q6;
   ...:
   ...:     cx q6[1], q6[2];"""

In [3]: module = pyqasm.load(qasm_str)

In [4]: module.num_qubits
Out[4]: 19

In [5]: module.num_clbits
Out[5]: 0

In [6]: module.validate()

In [7]: module.unroll()

In [8]: module.unrolled_qasm.splitlines()
Out[8]:
['OPENQASM 3.0;',
 'include "stdgates.inc";',
 'qubit[2] q1;',
 'qubit[2] q2;',
 'qubit[3] q3;',
 'qubit[1] q4;',
 'qubit[5] q5;',
 'qubit[3] qr;',
 'x q1[0];',
 'y q2[1];',
 'z q3[0];',
 'z q3[1];',
 'z q3[2];',
 'qubit[3] q6;',
 'cx q6[1], q6[2];']

In [9]: module.has_measurements()
Out[9]: False

In [10]: module.remove_measurements()
Out[10]: <pyqasm.modules.Qasm3Module at 0x107406540>

In [11]: module.depth()
Out[11]: 1

Users can also choose to pass an in_place=False argument to the methods above and get a new QasmModule object with the applied changes -

In [1]: import pyqasm

In [2]: qasm_str = """OPENQASM 3.0;
   ...:     gate custom q1, q2, q3{
   ...:         x q1;
   ...:         y q2;
   ...:         z q3;
   ...:     }
   ...:     qreg q1[2];
   ...:     qubit[2] q2;
   ...:     qubit[3] q3;
   ...:     qubit q4;
   ...:     qubit[5]   q5;
   ...:     qreg qr[3];
   ...:
   ...:     x q1[0];
   ...:     y q2[1];
   ...:     z q3;"""

In [3]: module = pyqasm.load(qasm_str)

In [4]: module.validate()

In [5]: module_copy = module.remove_measurements(in_place=False)
  • Restructured the pyqasm package to have a modules subpackage which contains the QasmModule, Qasm2Module and Qasm3Module classes (#62)

Deprecated

Removed

Fixed

  • Bug in initial sizes of classical registers. bit c; was being initialized with size 32 instead of 1 (#43)
  • Fixed bug in the handling of classical register type. Whenever a bit was referenced in an expression, it was treated as a scalar when it should be treated as an element of a 1D array with type bit (#44)

Dependencies

  • Update sphinx-autodoc-typehints requirement from <2.5,>=1.24 to >=1.24,<2.6 (#38)
  • Update sphinx requirement from <8.1.0,>=7.3.7 to >=7.3.7,<8.2.0 (#39)
  • Update sphinx-rtd-theme requirement from <3.0.0,>=2.0.0 to >=2.0.0,<4.0.0 (#40)

Full Changelog: v0.0.2...v0.0.3