A lightweight language to design quantum circuits and transpile them to Python code using Qiskit 2.x. Write simple gate instructions; Qupac parses, transpiles, and can run the generated Python for simulation.
Highlights
- Minimal syntax for qubit/classical declarations, gate application, measurement, and simulate.
- CLI runs generated Python in the background by default on Windows.
- Optionally emit the generated Python without running it.
Project layout
qupac/grammar.lark— Lark grammar for the languagequpac/parser.py— Parser and transformer to an IRqupac/transpiler.py— IR -> Python (Qiskit 2.x) code generatorqupac/executor.py— Runs generated Python (bg/fg)qupac/cli.py— CLI entrypoint (background by default)main.qu— Example program
Language quick reference
- Use statement:
use qiskit - Qubits:
qubits: <int> - Classical bits (optional):
classical: <int> - Apply gate:
apply H to 0orapply CX from 0 to 1 - Entangle two qubits:
entangle 0,1(shorthand forapply CX from 0 to 1) - Put a qubit in superposition:
superpose 0(shorthand forapply H to 0) - Measure all:
measure all - Measure one:
measure 0 -> 0 - Execute:
simulate - Shots (number of measurement samples):
shots: 1024(default 1024 if not provided) - Optimization level for transpile:
optimize: 0|1|2|3(maps to Qiskit's optimization_level) - Draw the generated circuit:
drawordraw mpl(text drawing is default;mplattempts a matplotlib rendering) - Simulator backend method:
simulator: default|statevector|unitary - Simple noise model (depolarizing):
noise depol p=0.01(requires qiskit-aer noise modules) - Comments: lines starting with
#or//
Example main.qu
use qiskit
qubits: 3 classical: 3
apply H to 0 apply CX from 0 to 1 apply CX from 1 to 2
measure all
simulate
Other shorthand examples
use qiskit
qubits: 2
entangle 0,1
measure all
simulate
Or using superpose:
use qiskit
qubits: 1
superpose 0
measure all
simulate
Draw and simulation options
use qiskit
qubits: 2
entangle 0,1
draw
shots: 2048
optimize: 1
simulate
This will print a textual drawing of the circuit, transpile with optimization level 1, and run the simulator with 2048 shots.
Parameterized gates and statevector
use qiskit
qubits: 1
apply RY(1.5708) to 0
draw
simulator: statevector
shots: 1
simulate
Noise (depolarizing) example
use qiskit
qubits: 2
entangle 0,1
noise depol p=0.02
shots: 2048
simulate
Setup
- Create and activate a Python 3.9+ environment.
- Install dependencies (Qiskit is large; installing only Lark lets you test parsing/transpiling):
- Minimal (parser/transpiler only): pip install lark
- Full (to actually run/simulate): pip install -r requirements.txt
Developer setup (lint, type-check, tests)
-
Install dev tools:
- Using pip: pip install -e .[dev]
- Or install individually: pip install ruff mypy pytest
-
Lint (Ruff): ruff check .
-
Type check (mypy): mypy qupac
-
Run tests (pytest): pytest -q
How to run
-
Dev, without installing the package:
- Emit generated Python (no Qiskit needed): python -m qupac.cli --emit main.qu
- Run generated Python in the background (requires Qiskit installed): python -m qupac.cli main.qu
- Run in foreground/blocking (requires Qiskit installed): python -m qupac.cli --fg main.qu
-
Install CLI (optional) to get the
qupaccommand: pip install -e . qupac --emit main.qu qupac main.qu
Background execution and logs
- By default, Qupac runs the generated Python script in the background.
- Logs are written to
.qupac_build/in your Qupac source folder. If you provide--log, output goes to that file.
Notes and limitations
- Rotation gates RX/RY/RZ need an angle; supported as numeric or expressions (e.g.,
pi/2). - Measuring a specific qubit (e.g.,
measure 0 -> 0) requires an explicitclassical: Ndeclaration. - Targeted for Qiskit 2.x APIs via
qiskitandqiskit-aerpackages.
Troubleshooting
- If your IDE shows "Invalid Python interpreter" or unresolved imports, make sure you’ve selected the correct Python environment and installed dependencies.
- If background runs don’t produce output, check
.qupac_build/*.logfiles for error messages (e.g., missing Qiskit).
License
- MIT (add your license as appropriate)