Releases: qBraid/pyqasm
PyQASM 0.5.0
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
andBox
support forOPENQASM3
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
andComplex
type inOPENQASM3
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 inelements.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 aScopeManager
. This change is introduced to ensure that theQasmVisitor
and thePulseVisitor
can share the sameScopeManager
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 addedmax_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
- @LukeAndreesen made their first contribution in #236
Full Changelog: v0.4.0...v0.5.0
PyQASM 0.4.0
Release 0.4.0 (June 17, 2025)
Summary
Added
- Added the
pulse
extra dependency to thepyproject.toml
file, which includes theopenpulse
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 useunroll
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
inQasmVisitor
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
- @samuraikillers made their first contribution in #194
- @arunjmoorthy made their first contribution in #195
- @antalszava made their first contribution in #198
- @vinayswamik made their first contribution in #200
- @bhagyasreey made their first contribution in #206
Full Changelog: v0.3.2...v0.4.0
PyQASM 0.3.2
Release 0.3.2 (April 25, 2025)
Summary
Added
Improved / Modified
Deprecated
Removed
Fixed
- Fixed bugs in the
PARAMS_OP_SET
by adding entries foru1
,prx
andcphaseshift10
gates. These gates were required to correctly run the tests forqbraid-qir
and theqBraid
packages. (#176) (#177)
Dependencies
Other
What's Changed
- Reset the changelog [no ci] by @TheGupta2012 in #173
- Bump codecov/codecov-action from 5.4.0 to 5.4.2 by @dependabot in #174
- Add u1 to params map by @TheGupta2012 in #176
- Add prx, cphaseshift 10 to param map by @TheGupta2012 in #177
- Bump project version to 0.3.2 by @github-actions in #178
Full Changelog: v0.3.1...v0.3.2
PyQASM 0.3.1
Release 0.3.1 (April 21, 2025)
Summary
Added
- Added support for conditionally unrolling barrier statements in the
unroll
method with theunroll_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 totrue
/false
to enable / disable the expansion of traceback information in the error messages. The default is set asfalse
. (#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
andpyqasm.printer.mpl_draw
behaviour for multiple function calls. See issue #165 for bug details. (#168)
Dependencies
PRs Merged
- Reset CHANGELOG.md [no ci] by @ryanhill1 in #164
- Add conditional barrier unrolling by @TheGupta2012 in #166
- Update Changelog [no ci] by @TheGupta2012 in #167
- Fix draw bug in pyqasm printer by @TheGupta2012 in #168
- Add params validation for basic gates by @TheGupta2012 in #169
- Replace
Union
with|
by @TheGupta2012 in #170 - Improve error reporting for pyqasm by @TheGupta2012 in #171
- Bump project version to 0.3.1 by @github-actions in #172
Full Changelog: v0.3.0...v0.3.1
PyQASM 0.3.0
Release 0.3.0 (Mar 18, 2025)
Summary
Added
- Added logic to
bump-version.yml
workflow that automatically updatesCITATION.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')
- 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__
andimportlib.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
- write version file test pypi by @ryanhill1 in #145
- fix typo in write_version_file.py [no ci] by @ryanhill1 in #146
- Versioning fixes cont + citation by @ryanhill1 in #147
- Add yaml dep to bump-version [no ci] by @ryanhill1 in #148
- Update bump-version.yml [no ci] by @ryanhill1 in #149
- Update bump-version.yml [no ci] by @ryanhill1 in #151
- Update sphinx requirement from <8.2.0,>=7.3.7 to >=7.3.7,<8.3.0 by @dependabot in #153
- Update sphinx-autodoc-typehints requirement from <3.1,>=1.24 to >=1.24,<3.2 by @dependabot in #154
- Add check for duplicate qubits post gate broadcast by @TheGupta2012 in #155
- Change license to Apache-2.0 by @ryanhill1 in #158
- Bump codecov/codecov-action from 4.4.1 to 5.4.0 by @dependabot in #159
- Update README.md [no ci] by @ryanhill1 in #160
- Reset CHANGELOG.md [no ci] by @ryanhill1 in #161
- QasmModule Circuit Drawer by @arulandu in #122
- Add
pyqasm.draw()
to changelog [no ci] by @ryanhill1 in #162 - Bump project version to 0.3.0 by @github-actions in #163
Full Changelog: v0.2.1...v0.3.0
PyQASM 0.2.1
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
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 theQasmModule
. Users now have the ability to rebase the quantum programs to any of the availablepyqasm.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 withctrl @
modifiers can now be loaded asQasmModule
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 fixqbraid 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
- @devilkiller-ag made their first contribution in #106
- @arulandu made their first contribution in #112
- @PranavTupe2000 made their first contribution in #123
Full Changelog: v0.1.0...v0.2.0
PyQASM 0.1.0
Release 0.1.0 (Dec 10, 2024)
Summary
Added
- Added support for
gphase
,toffoli
,not
,c3sx
andc4x
gates (#86) - Added a
remove_includes
method toQasmModule
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 thepre_build.sh
script. (#99)
Deprecated
Removed
Fixed
- Fixed bugs in implementations of
gpi2
andprx
gates (#86)
Dependencies
Full Changelog:
PyQASM 0.1.0-alpha
Release 0.1.0-alpha (Nov 28, 2024)
Summary
Added
- Added a
dumps
andformatted_qasm
method to theQasmModule
class to allow for the conversion of aQasmModule
object to a string representation of the QASM code (#71) - Added the
populate_idle_qubits
method to theQasmModule
class to populate idle qubits with anid
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 anexternal_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
, anddumps
functions to thepyqasm
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 aQasmModule
object contains barriers (#85) - Added
pyqasm.cli
module withtyper
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 theQasmModule
class to only accept anopenqasm3.ast.Program
object as input (#71) - Changed
DepthNode
,QubitDepthNode
,ClbitDepthNode
, andVariable
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
redundantKeyError
handling with loop (#79) - The
load
function has been renamed toloads
andload
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
topyqasm.linalg_cy
with ~60% speedup - Migrated
pyqasm.linalg._so4_to_so2()
to topyqasm.linalg_cy
with ~5% speedup
- Migrated
- 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 theQasmModule
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
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 theQasmModule
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 theQasmModule
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 theQasm2Module
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
andpyqasm.validate.py
intopyqasm.entrypoint.py
with newpyqasm.load()
function which returns aQasm3Module
(#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
andvalidate
functions. Introduced a newload
function that returns aQasmModule
object, which can be used to then callunroll
andvalidate
. Also added methods likeremove_measurements
,remove_barriers
,has_measurements
anddepth
to theQasmModule
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 amodules
subpackage which contains theQasmModule
,Qasm2Module
andQasm3Module
classes (#62)
Deprecated
Removed
Fixed
- Bug in initial sizes of classical registers.
bit c;
was being initialized with size32
instead of1
(#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 typebit
(#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