Tensor Operations for Research in Quantum systems.
Project description
TorQ Quantum Library
TorQ is a lightweight, Torch-based statevector library for fast quantum layers inside neural networks.
Developed while writing the paper: Quantum Physics-Informed Neural Networks for Maxwell's Equations: Circuit Design, "Black Hole" Barren Plateaus Mitigation, and GPU Acceleration
by Ziv Chen, Gal G. Shaviner, Hemanth Chandravamsi, Shimon Pisnoy, Steven H. Frankel, Uzi Pereg
https://arxiv.org/abs/2506.23246
For the simpler version associated with the following paper, please use the simple_for_PINNACLE branch: PINNACLE: An Open-Source Computational Framework for Classical and Quantum PINNs
by Shimon Pisnoy, Hemanth Chandravamsi, Ziv Chen, Aaron Goldgewert, Gal Shaviner, Boris Shragner, Steven H. Frankel
https://arxiv.org/abs/2604.15645
It is compatible with the TorQ-bench simple_for_PINNACLE branch and the PINNACLE repos.
When to use
- You want a differentiable quantum layer inside a PyTorch model.
- You care about batched statevector throughput on CPU or GPU.
- You need analytic expectation values rather than shot-based sampling.
When not to use
- You need realistic hardware noise models or error channels.
- You need shot-based measurements or sampling.
- You need hardware-aware compilation or execution on QPUs.
- You need multi-GPU or distributed statevector simulation.
What this library optimizes for
- Speed inside a neural-network forward and backward pass.
- Batched evaluation of many inputs at once.
- Single-device training workflows.
This library was benchmarked primarily on NVIDIA L40s and A100 GPUs. Performance on other hardware has not been tuned and may differ.
Install
TorQ requires Python 3.10+ and PyTorch 1.13+.
# install from PyPI
python -m pip install torq-quantum
# optional: editable install for local development
python -m pip install -e .
The PyPI package name is torq-quantum, while the Python import path is torq.
If you want to use the optional PennyLane comparison backend, you also need importable pennylane and torq_bench packages in the same environment.
Quickstart
torq.simple.Circuit is the recommended student-facing API.
import torch
from torq.simple import Circuit, CircuitConfig
circuit = Circuit(
n_qubits=4,
n_layers=2,
ansatz_name="basic_entangling",
config=CircuitConfig(),
)
x = torch.rand(8, 4)
y = circuit(x)
print(y.shape) # torch.Size([8, 4])
By default, the output is the local Pauli-Z expectation value on each qubit, so the shape is [batch, n_qubits].
Student-facing API
Circuit:torch.nn.Modulewrapper around TorQ's internalQLayer.CircuitConfig: configuration object for encoding, ansatz options, measurements, and backend selection.circuit.params: trainable main parameter tensor.circuit.params_last_layer_reupload: extra trainable tensor used only whendata_reupload_every > 0.
TorQ also exposes lower-level helpers through torq.simple:
from torq.simple import (
angle_embedding,
data_reuploading,
data_reuploading_gates,
get_initial_state,
measure,
)
Supported ansatzes
TorQ currently supports these ansatz names:
basic_entanglingsingle_rot_basic_entstrongly_entanglingtilecross_meshcross_mesh_2_rotscross_mesh_cx_rotno_entanglement_ansatz
Notes:
single_rot_basic_entuses the same CNOT ladder asbasic_entangling, but only one rotation parameter per qubit. The rotation axis is chosen withsingle_rotation_gate.tileuses a brick-wall CNOT pattern. Within each sublayer it applies(0,1), (2,3), ..., then(1,2), (3,4), .... Iftile_cyclic=Trueandn_qubitsis even, it also adds a wraparoundCX(n_qubits - 1, 0)per sublayer.no_entanglement_ansatzapplies only single-qubit rotations.
Relevant CircuitConfig fields:
single_rotation_gate: rotation axis used bysingle_rot_basic_ent, and bytilewhentile_rotation_params=1. Supported values are"x","rx","y","ry","z","rz".tile_rotation_params:1or3.tile_sublayers: number of repeated brick-wall sublayers per layer.tile_cyclic: whethertileadds the even-qubit wraparound CNOT.
Example: tile
import torch
from torq.simple import Circuit, CircuitConfig
cfg = CircuitConfig(
tile_rotation_params=1,
single_rotation_gate="rz",
tile_sublayers=2,
tile_cyclic=True,
)
circuit = Circuit(
n_qubits=6,
n_layers=2,
ansatz_name="tile",
config=cfg,
)
x = torch.rand(8, 6)
y = circuit(x)
Angle embedding and scaling
CircuitConfig controls angle embedding with these fields:
basis_angle_embedding:"x","rx","y","ry","z", or"rz".angle_scaling_method:"none","scale","scale_with_bias","asin", or"acos".angle_scaling: scaling factor used by"scale"and"scale_with_bias".
The nonlinear scaling modes are mainly intended for inputs that already live near [-1, 1], for example after a tanh.
Scaling methods:
"none": leaves the input unchanged."scale": computesangles * angle_scaling."scale_with_bias": computes(angles + 1) * (angle_scaling / 2)."asin": computesasin(angles) + pi / 2after a small internal clamp for numerical stability."acos": computesacos(angles)after a small internal clamp for numerical stability.
import torch
from torq.simple import Circuit, CircuitConfig
cfg = CircuitConfig(
angle_scaling_method="scale",
angle_scaling=torch.pi,
basis_angle_embedding="Y",
)
circuit = Circuit(
n_qubits=4,
n_layers=2,
ansatz_name="basic_entangling",
config=cfg,
)
x = torch.rand(8, 4)
y = circuit(x)
Data reuploading
Set data_reupload_every > 0 to enable TorQ's legacy repeated-upload execution scheme.
When data_reupload_every = k:
- each logical layer applies
kansatz blocks before a data upload, - after the final upload, TorQ applies one more tail of
kansatz blocks, - the model therefore owns both
circuit.paramsandcircuit.params_last_layer_reupload.
This increases simulation cost and memory use.
import torch
from torq.simple import Circuit, CircuitConfig
cfg = CircuitConfig(data_reupload_every=2)
circuit = Circuit(
n_qubits=4,
n_layers=2,
ansatz_name="cross_mesh",
config=cfg,
)
x = torch.rand(8, 4)
y = circuit(x)
Notes:
- For
strongly_entangling,data_reupload_everymust be<= n_layers. - If you pass manual weights and
data_reupload_every == 0,weightsmay be shaped as either[n_layers, ...]or[n_layers, 1, ...]. - If you pass manual weights and
data_reupload_every > 0,weightsmust have shape[n_layers, data_reupload_every, ...], andweights_last_layer_data_remust have shape[data_reupload_every, ...].
Measurements and observables
Use CircuitConfig(observables=...) to control the output measurement.
Supported inputs:
None: default local Pauli-Z on every qubit, returning[batch, n_qubits].- Pauli string: one or more Pauli words separated by
_, case-insensitive. - Hermitian matrix or matrices:
[2, 2]shared local observable for every qubit[n_qubits, 2, 2]per-qubit local observables[2**n, 2**n]one full-system observable[m, 2**n, 2**n]multiple full-system observables
Pauli-string rules:
- Allowed characters are
I,X,Y,Z, and_. - A Pauli word of length
Lis measured on every contiguousL-qubit window. _concatenates multiple Pauli-word groups into one output tensor.- An all-identity observable such as
"I_I_I"is rejected.
Examples:
"z"returns localZ_ion every qubit."xx"returnsX_i X_{i+1}on every adjacent pair."z_zz_x"returns allZ_i, then allZ_i Z_{i+1}, then allX_i.
pauli_measurement_chunk_size tunes the throughput-versus-memory tradeoff for grouped Pauli-string measurements. Repeated all-Z words such as "zz" and "zzz" use a dedicated fast path.
import torch
from torq.simple import Circuit, CircuitConfig
q = 4
cfg = CircuitConfig(
observables="z_zz_x",
pauli_measurement_chunk_size=8,
)
circuit = Circuit(
n_qubits=q,
n_layers=2,
ansatz_name="basic_entangling",
config=cfg,
)
x = torch.rand(8, q)
y = circuit(x)
print(y.shape) # torch.Size([8, 11])
If local Pauli-Z is the only output you need, leaving observables=None is still the fastest path.
Initialization and advanced options
Useful CircuitConfig flags:
init_identity=True: initialize all parameters to0.init_ones=True: initialize all parameters topi.init_pi_half=True: initialize all parameters topi / 2.reparametrize_sin_cos=True: internally wraps angles throughatan2(sin(theta), cos(theta)).pennylane_backend=True: try to run through the optional PennyLane comparison backend.pennylane_dev_name: PennyLane device name, defaulting to"default.qubit".
noise_all_q_layers is only used by TorQ's legacy param_init_dict initialization path.
Optional PennyLane backend
TorQ can optionally delegate execution to a PennyLane comparison backend:
from torq.simple import Circuit, CircuitConfig
cfg = CircuitConfig(
pennylane_backend=True,
pennylane_dev_name="default.qubit",
)
circuit = Circuit(
n_qubits=2,
n_layers=1,
ansatz_name="strongly_entangling",
config=cfg,
)
Notes:
- TorQ only uses this path if both
pennylaneandtorq_benchare importable. - If the requested basis, observables, or ansatz are unsupported by the PennyLane comparison backend, TorQ emits a warning and falls back to the native TorQ backend.
- This path is mainly useful for parity checks and benchmarking rather than for normal TorQ usage.
Benchmarking
For benchmark scripts and PennyLane comparisons, use the TorQ-bench repository:
https://github.com/zivchen9993/TorQ-bench
Limitations
- Statevector simulation only, so memory scales as
O(2^n_qubits). - Analytic measurements only; no shots or sampling.
- Ideal, noise-free gates and measurements.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
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 torq_quantum-0.1.3.tar.gz.
File metadata
- Download URL: torq_quantum-0.1.3.tar.gz
- Upload date:
- Size: 36.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a92793d331143397b353e9735e472ad12bbe4e2d2ed8a4c107276ebf237ef0c6
|
|
| MD5 |
37175658ca212766a2f9e84577bed413
|
|
| BLAKE2b-256 |
02b6ab27d4e44c3cfcc6be3a338442fde043b02ac352c4de08b3c0a6316fb8ab
|
File details
Details for the file torq_quantum-0.1.3-py3-none-any.whl.
File metadata
- Download URL: torq_quantum-0.1.3-py3-none-any.whl
- Upload date:
- Size: 31.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a301312da3b88f4726b48bf32fef87725a5d1c30fd6d764f0ccc8080cae370dc
|
|
| MD5 |
b8ecc697ba27938447c3788d808a66ba
|
|
| BLAKE2b-256 |
c3931c28c4ce5b49c85bc0c066fc78da7fc917545571063424e0d4930d3bc942
|