Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
qbraid_algorithms/openpulse/scripts/
316 changes: 316 additions & 0 deletions examples/openpulse/gaussian_pulse.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "8818805c",
"metadata": {},
"source": [
"# Gaussian OpenPulse waveform generator\n",
"\n",
"This notebook shows how to use `qbraid_algorithms.openpulse` to generate an **OpenQASM 3 + OpenPulse** program that defines a **Gaussian** waveform and a `defcal` that plays it on a target qubit."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "b14ce19a",
"metadata": {},
"outputs": [],
"source": [
"import pyqasm\n",
"\n",
"from qbraid_algorithms.openpulse import GaussianPulse, PulseParams, generate_program\n"
]
},
{
"cell_type": "markdown",
"id": "0eec9271",
"metadata": {},
"source": [
"## Generate a standalone Gaussian pulse QASM program"
]
},
{
"cell_type": "markdown",
"id": "08e0e059",
"metadata": {},
"source": [
"First we define the parameters of the pulse we want to play on a target qubit."
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "30727e52",
"metadata": {},
"outputs": [],
"source": [
"pulse = GaussianPulse(amplitude=1.0 + 2.0j, duration=\"16ns\", sigma=\"4ns\")\n",
"params = PulseParams(\n",
" frame_frequency=5.0e9,\n",
" frame_phase=0.0,\n",
" port_name=\"d0\",\n",
" frame_name=\"driveframe\",\n",
" waveform_name=\"wf\",\n",
" defcal_name=\"play_gaussian\",\n",
" qubit=0,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "276571ed",
"metadata": {},
"source": [
"Then we pass the parameters to a `generate_program()` call to load a PyQASM module that defines and plays the pulse."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "d6f8d58a",
"metadata": {},
"outputs": [],
"source": [
"module = generate_program(pulse=pulse, params=params)"
]
},
{
"cell_type": "markdown",
"id": "7df56c25",
"metadata": {},
"source": [
"After loading the program as a PyQASM module, we can run all the standard PyQASM operations on it, such as displaying it:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "16944412",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OPENQASM 3.0;\n",
"defcalgrammar \"openpulse\";\n",
"cal {\n",
" port d0;\n",
" frame driveframe = newframe(d0, 5000000000.0, 0.0);\n",
" waveform wf = gaussian(1.0 + 2.0im, 16ns, 4ns);\n",
"}\n",
"defcal play_gaussian() $0 {\n",
" play(driveframe, wf);\n",
"}\n",
"\n"
]
}
],
"source": [
"print(pyqasm.dumps(module))"
]
},
{
"cell_type": "markdown",
"id": "4535603f",
"metadata": {},
"source": [
"or unrolling it:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "7f3c924f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OPENQASM 3.0;\n",
"qubit[1] __PYQASM_QUBITS__;\n",
"defcalgrammar \"openpulse\";\n",
"cal {\n",
" port d0;\n",
" frame driveframe = newframe(d0, 5000000000.0, 0.0, 0ns);\n",
" waveform wf = gaussian(1.0 + 2.0im, 16.0ns, 4.0ns);\n",
"}\n",
"defcal play_gaussian() $0 {\n",
" play(driveframe, wf);\n",
"}\n",
"\n"
]
}
],
"source": [
"unrolled = module.copy()\n",
"unrolled.unroll()\n",
"\n",
"print(pyqasm.dumps(unrolled))"
]
},
{
"cell_type": "markdown",
"id": "a76f9284",
"metadata": {},
"source": [
"## Example: Qubit Spectroscopy"
]
},
{
"cell_type": "markdown",
"id": "52d3f2e8",
"metadata": {},
"source": [
"Qubit spectroscopy is a common pulse-level experiment where the qubit is driven with the same pulse\n",
"while the drive frequency is swept. By observing the qubit’s response as a function of frequency,\n",
"its transition frequency can be identified.\n",
"\n",
"In this example, we use the Gaussian OpenPulse generator to define a reusable pulse waveform and a\n",
"`defcal` routine that plays it on a drive frame. This calibration is then called inside a frequency\n",
"sweep loop, showing how the generator can be used as a building block for larger pulse-level\n",
"experiments."
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "3362ad37",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OPENQASM 3.0;\n",
"defcalgrammar \"openpulse\";\n",
"cal {\n",
" port d0;\n",
" frame driveframe = newframe(d0, 5000000000.0, 0.0);\n",
" waveform wf = gaussian(1.0 + 2.0im, 16ns, 4ns);\n",
"}\n",
"defcal play_gaussian() $0 {\n",
" play(driveframe, wf);\n",
"}\n",
"\n",
"const float frequency_start = 4.5e9;\n",
"const float frequency_step = 1e6;\n",
"const int frequency_num_steps = 3;\n",
"\n",
"cal {\n",
" set_frequency(driveframe, frequency_start);\n",
"}\n",
"\n",
"for int i in [1:frequency_num_steps] {\n",
" cal {\n",
" shift_frequency(driveframe, frequency_step);\n",
" }\n",
" play_gaussian $0;\n",
" measure $0;\n",
"}\n",
"\n"
]
}
],
"source": [
"import pyqasm\n",
"\n",
"base_module = generate_program(pulse=pulse, params=params)\n",
"base_qasm = pyqasm.dumps(base_module).rstrip()\n",
"\n",
"qubit_spectroscopy_qasm_code = base_qasm + f\"\"\"\n",
"\n",
"const float frequency_start = 4.5e9;\n",
"const float frequency_step = 1e6;\n",
"const int frequency_num_steps = 3;\n",
"\n",
"cal {{\n",
" set_frequency({params.frame_name}, frequency_start);\n",
"}}\n",
"\n",
"for int i in [1:frequency_num_steps] {{\n",
" cal {{\n",
" shift_frequency({params.frame_name}, frequency_step);\n",
" }}\n",
" {params.defcal_name} ${params.qubit};\n",
" measure ${params.qubit};\n",
"}}\n",
"\"\"\"\n",
"\n",
"print(qubit_spectroscopy_qasm_code)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "deb69867",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"OPENQASM 3.0;\n",
"qubit[1] __PYQASM_QUBITS__;\n",
"defcalgrammar \"openpulse\";\n",
"cal {\n",
" port d0;\n",
" frame driveframe = newframe(d0, 5000000000.0, 0.0, 0ns);\n",
" waveform wf = gaussian(1.0 + 2.0im, 16.0ns, 4.0ns);\n",
"}\n",
"defcal play_gaussian() $0 {\n",
" play(driveframe, wf);\n",
"}\n",
"cal {\n",
" set_frequency(driveframe, 4500000000.0);\n",
"}\n",
"cal {\n",
" shift_frequency(driveframe, 4501000000.0);\n",
"}\n",
"play_gaussian __PYQASM_QUBITS__[0];\n",
"measure __PYQASM_QUBITS__[0];\n",
"cal {\n",
" shift_frequency(driveframe, 4502000000.0);\n",
"}\n",
"play_gaussian __PYQASM_QUBITS__[0];\n",
"measure __PYQASM_QUBITS__[0];\n",
"cal {\n",
" shift_frequency(driveframe, 4503000000.0);\n",
"}\n",
"play_gaussian __PYQASM_QUBITS__[0];\n",
"measure __PYQASM_QUBITS__[0];\n",
"\n"
]
}
],
"source": [
"qubit_spectroscopy_module = pyqasm.loads(qubit_spectroscopy_qasm_code)\n",
"qubit_spectroscopy_module.unroll()\n",
"print(pyqasm.dumps(qubit_spectroscopy_module))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "qbraid-algos",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ cli = [
"rich>=10.11.0",
"typing-extensions"
]
pulse = [
"pyqasm[pulse]"
]

[project.scripts]
qbraid-algorithms = "qbraid_algorithms.cli.main:app"
Expand Down
18 changes: 18 additions & 0 deletions qbraid_algorithms/openpulse/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2026 qBraid
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""OpenPulse generators for qbraid-algorithms."""
from .gaussian import GaussianPulse, PulseParams, generate_program

__all__ = ["GaussianPulse", "PulseParams", "generate_program"]
Loading