A quantum programming language and compiler.
Project description
Spinach lang
Spinach is a quantum programming language.
Its goal is to provide a dedicated language that can simulate and compile code for execution on quantum computers.
Installation
Standard (Linux / macOS / Windows)
Requires Python 3.10+ and uv.
# 1. Create and activate a virtual environment
uv venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 2. Install the package
uv pip install spinachlang
# 3. Verify
spinachlang --help
To also install optional quantum backend extensions (Cirq, Quil, Qiskit, etc.):
uv pip install "spinachlang[backends]"
NixOS
PyTKET requires libstdc++.so.6 which is not in the default library search path on NixOS.
shell.nix sets LD_LIBRARY_PATH to expose it automatically.
On NixOS 24.05+, NIX_PATH contains a flake:nixpkgs entry, which causes nix-shell
to fail with "experimental Nix feature 'flakes' is disabled" unless flakes are enabled.
Enable them once with:
mkdir -p ~/.config/nix
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
Then install normally:
# 1. Enter the dev shell (sets LD_LIBRARY_PATH for pytket)
nix-shell
# 2. Create and activate a virtual environment
uv venv
source .venv/bin/activate
# 3. Install the package
uv pip install .
# 4. Verify
spinachlang --help
Or as a one-liner:
nix-shell --run 'uv pip install . && .venv/bin/spinachlang --help'
Note: always run
spinachlangfrom insidenix-shell(or with theLD_LIBRARY_PATHit sets) so that pytket's C++ extensions can findlibstdc++.so.6.
Usage
spinachlang -l qasm path/to/program.sph # compile to OpenQASM
spinachlang -l cirq path/to/program.sph # compile to Cirq (Python)
spinachlang -l quil path/to/program.sph # compile to Quil
spinachlang -l json path/to/program.sph # compile to TKET JSON
spinachlang -l qasm path/to/program.sph -o out.qasm # specify output file
cat program.sph | spinachlang -l qasm - # read from stdin, write to stdout
Development Setup
# Clone the repository
git clone https://github.com/spinachlang/spinachlang.git
cd spinachlang
# NixOS: enter the dev shell first
nix-shell # sets LD_LIBRARY_PATH for pytket
# Install with dev dependencies
uv pip install ".[dev]"
Testing
# Run all tests
.venv/bin/pytest tests/
# Run a specific test module
.venv/bin/pytest tests/test_compiler.py
# Run with verbose output
.venv/bin/pytest tests/ -v
# Run with coverage
.venv/bin/pytest tests/ --cov=spinachlang
On NixOS, run tests from inside nix-shell:
nix-shell --run '.venv/bin/pytest tests/ -v'
Gate Reference
All angles are expressed in half-turns (multiples of π).
RX(0.5) = rotation by π/2 rad. Decimal literals are supported: RX(0.5), TK1(0.25, 0.5, 0.75), etc.
Single-qubit gates
| Spinach name | PyTKET gate | Parameters | Notes |
|---|---|---|---|
H |
H |
— | Hadamard |
X / N |
X |
— | Pauli X / NOT |
Y |
Y |
— | Pauli Y |
Z |
Z |
— | Pauli Z |
S |
S |
— | S gate |
ST |
Sdg |
— | S† |
T |
T |
— | T gate |
TT |
Tdg |
— | T† |
SX |
SX |
— | √X |
SXDG |
SXdg |
— | √X† |
V |
V |
— | V gate (≡ √X in TKET) |
VDG |
Vdg |
— | V† |
RX(a) |
Rx |
1 angle | Rotation around X |
RY(a) |
Ry |
1 angle | Rotation around Y |
RZ(a) |
Rz |
1 angle | Rotation around Z |
U1(λ) |
U1 |
1 angle | IBM diagonal gate |
U2(φ,λ) |
U2 |
2 angles | IBM 2-angle gate |
U3(θ,φ,λ) |
U3 |
3 angles | IBM full SU(2) |
TK1(α,β,γ) |
TK1 |
3 angles | TKET Euler decomposition |
PX(exp,ph) / PHASEDX(exp,ph) |
PhasedX |
2 angles | X rotation around a phase-shifted axis |
RESET / R |
Reset |
— | Reset to |0⟩ |
Two-qubit gates
Convention: target -> GATE(…, ctrl_or_partner) — the last positional arg is always the partner qubit (by integer index or name).
| Spinach name | PyTKET gate | Parameters | Notes |
|---|---|---|---|
CX(ctrl) / CNOT(ctrl) |
CX |
ctrl | Controlled-X |
FCX(ctrl) / FCNOT(ctrl) |
CX (flipped) |
ctrl | CX with roles swapped |
CY(ctrl) |
CY |
ctrl | Controlled-Y |
FCY(ctrl) |
CY (flipped) |
ctrl | |
CZ(ctrl) |
CZ |
ctrl | Controlled-Z |
FCZ(ctrl) |
CZ (flipped) |
ctrl | |
CH(ctrl) |
CH |
ctrl | Controlled-H |
FCH(ctrl) |
CH (flipped) |
ctrl | |
CU1(a,ctrl) |
CU1 |
1 angle + ctrl | Controlled-U1 |
CRX(a,ctrl) |
CRx |
1 angle + ctrl | Controlled-Rx |
CRY(a,ctrl) |
CRy |
1 angle + ctrl | Controlled-Ry |
CRZ(a,ctrl) |
CRz |
1 angle + ctrl | Controlled-Rz |
SWAP(other) |
SWAP |
other | SWAP |
ECR(ctrl) |
ECR |
ctrl | Echoed Cross-Resonance |
ISWAP(a,other) |
ISWAP |
1 angle + other | iSWAP with phase |
ISWAPMAX(other) |
ISWAPMax |
other | Maximal iSWAP (≡ ISWAP(1)) |
ZZMAX(other) |
ZZMax |
other | ZZMax (≡ ZZPhase(½)) |
ZZPH(a,other) |
ZZPhase |
1 angle + other | ZZ interaction |
XXPH(a,other) |
XXPhase |
1 angle + other | XX interaction |
YYPH(a,other) |
YYPhase |
1 angle + other | YY interaction |
FSIM(θ,φ,other) |
FSim |
2 angles + other | Fermionic Simulation |
TK2(a,b,c,other) |
TK2 |
3 angles + other | TKET canonical 2-qubit |
PHISWAP(p,t,other) |
PhasedISWAP |
2 angles + other | Phased iSWAP |
Three-qubit gates
| Spinach name | PyTKET gate | Parameters | Notes |
|---|---|---|---|
CCX(c1,c2) / TOFFOLI(c1,c2) |
CCX |
2 controls | Toffoli |
CSWAP(ctrl,other) / FREDKIN(ctrl,other) |
CSWAP |
ctrl + other | Fredkin — swaps target↔other when ctrl=|1⟩ |
XXP3(a,q1,q2) |
XXPhase3 |
1 angle + 2 partners | Simultaneous XX on all pairs |
Measurement & classical
| Spinach name | Effect | Notes |
|---|---|---|
M / MEASURE |
Measure to classical bit | * -> M measures all qubits |
BARRIER |
Synchronisation point | Cross-qubit, no-reorder fence |
SET(0|1) |
Set bit to 0 or 1 | Classical bit target |
NOT / NOT(src) |
Classical NOT | In-place or with source |
AND(b0,b1) |
Classical AND | 2 bit args |
OR(b0,b1) |
Classical OR | 2 bit args |
XOR(b0,b1) |
Classical XOR | 2 bit args |
COPY(src) |
Copy bit |
Global phase & CircBox
# Global phase: PHASE(angle) adds e^{i·angle·π} to the circuit scalar.
# The qubit target is syntactically required but ignored.
0 -> PHASE(0.5)
# CircBox: wrap a named instruction pipeline as a reusable black-box sub-circuit.
# The box has abstract qubits 0…n-1 mapping to the target list in order.
bell : H | CX(1)
q0 : q 0
q1 : q 1
[q0, q1] -> CIRCBOX(bell)
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spinachlang-0.4.0.tar.gz.
File metadata
- Download URL: spinachlang-0.4.0.tar.gz
- Upload date:
- Size: 43.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea433afd45ea12685707e107299a4514bf596cc4f0639b61a1e7268acb8ae6e3
|
|
| MD5 |
d831864337b57d14fd67965a44f096a8
|
|
| BLAKE2b-256 |
72112ec9e4447e8e4bbbedfbaccff4a1c23f8e0212676df6e7745942d4702631
|
File details
Details for the file spinachlang-0.4.0-py3-none-any.whl.
File metadata
- Download URL: spinachlang-0.4.0-py3-none-any.whl
- Upload date:
- Size: 28.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1462ae74b38adff3c588ec00273bddc755b36bd275b6d06e381cf770db6f3621
|
|
| MD5 |
88159de1367792dc833408f9684bb39f
|
|
| BLAKE2b-256 |
4d672c60bef1d44eed94c7f897f7395ca9faf195e3c9c0071c42630297e9b474
|