TorchQuantum: Parameterized Quantum Circuits Inside a PyTorch Autograd Graph
A PyTorch-based framework for Quantum Classical Simulation, Quantum Machine Learning, Quantum Neural Networks, Parameterized Quantum Circuits with support for easy deployments on real quantum computers.
At a glance
- What is it?
- TorchQuantum is MIT HAN Lab's PyTorch-native simulator for parameterized quantum circuits, aimed at researchers who want gradients, batching and GPU execution without leaving the PyTorch training loop. The design pays off for QML research and off for work that needs a large gate library or hardware-first workflows.
- Who is it for?
- Adopt TorchQuantum if your work is parameterized circuit training on a classical simulator and you want the optimizer, loss and gradient machinery to be ordinary PyTorch. Do not adopt it if you need pulse-level control today, a broad gate set, or a hardware-first workflow where the device is the primary target rather than the simulator.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 72 days ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap TorchQuantum fills: gradients through a circuit, not around it
Most quantum SDKs treat a circuit as a program you build, submit and read back. TorchQuantum treats it as a module inside a training loop. The README frames the project as simulating quantum computations on classical hardware using PyTorch, with statevector and pulse simulation on GPUs, and states it can scale to 30+ qubits with multiple GPUs. The audience named in the README is narrow and specific: researchers on quantum algorithm design, parameterized quantum circuit training, quantum optimal control, quantum machine learning and quantum neural networks. That is a research audience, not a production deployment audience. The README also lists what separates it from Qiskit and PennyLane: a dynamic computation graph, automatic gradient computation, fast GPU support and batch tensorized processing. Those four items are the whole pitch, and they are all about the training loop rather than about circuit expressiveness. If your problem is "I have a variational ansatz and I want to optimize its parameters with Adam," the project is aimed at you. If your problem is "I want to run a 100-qubit circuit on a vendor backend and read counts," it is not.
QuantumDevice, op_history and the tensorized state
The core object is tq.QuantumDevice. The README example constructs one with n_wires=2, bsz=5, device="cpu" and record_op=True. The bsz argument is the part worth pausing on: the state is not a single vector but a batch of five, so every gate application is a batched tensor operation. That is what makes the batch mode claim concrete rather than marketing. Gates can be applied three ways, all shown in the README: as methods on the device (qdev.h(wires=0), qdev.cnot(wires=[0, 1])), as functional calls (tqf.h(qdev, wires=1)), or as operator objects (tq.RX(has_params=True, trainable=True, init_params=0.5)) which are called with the device and a wire list. The trainable=True flag is what places the parameter in the autograd graph. record_op=True is what makes the other half of the API work: it records an op history on the device, and the README shows op_history2qasm(qdev.n_wires, qdev.op_history) from torchquantum.plugin turning that history into an OpenQASM string. That history is also the input to tq.QuantumModule.from_op_history(ops), which converts a list of dictionaries (name, wires, params, trainable, inverse) into a module. So the data flow is: build a device, apply gates, accumulate an op history, optionally replay that history as a module or export it as QASM. Measurement is a separate step. tq.measure(qdev, n_shots=1024) returns sampled bitstrings, expval_joint_sampling computes an expectation by sampling (the README notes this works on simulator and real hardware), and expval_joint_analytical computes it exactly (simulator only). Gradients come from calling backward on the expectation value and reading op.params.grad, which is ordinary PyTorch autograd.
Installation and the first ten lines
Installation is a source checkout rather than a plain pip install, per the README: git clone https://github.com/mit-han-lab/torchquantum.git, then cd torchquantum, then pip install --editable . The editable flag means you are installing the working tree, so local edits to the package take effect without reinstalling. That is convenient for research and inconvenient for reproducible environments, because your installed version is whatever your checkout happens to be. There is a PyPI package (the README carries a PyPI badge and the project publishes releases, most recently v0.1.8 in February 2024), but the README's own installation instructions use the clone path. Note the version numbering: v0.1.8, v0.1.7 and v0.1.6. This is pre-1.0 software. The README example also shows the intended first program, and it is short: import torchquantum as tq, import torchquantum.functional as tqf, construct a QuantumDevice with device="cuda" for GPU, apply a Hadamard and a CNOT, and you have a Bell state with a batch dimension. The README's guide to examples splits material into beginning, intermediate and expert tiers. Beginning includes QNN for MNIST, Quanvolution, Quantum Kernel Method and Quantum Regression. Intermediate includes Amplitude Encoding for MNIST, Clifford gate QNN, save and load, PauliSum operation, and a tq-to-Qiskit converter. Expert includes parameter shift on-chip training, VQA gradient pruning, VQE and state preparation. The tiering is honest about the learning curve: the on-chip training example is filed under expert, not beginner.
Where the design bites: pulse simulation, operator coverage and the dev branch
The README's feature list marks pulse-level simulation as "coming soon." The welcome section claims pulse simulation support on GPUs, and the feature list says it is coming. Those two statements do not agree, and the feature list is the more conservative one. Treat pulse-level work as not available in the released version until you confirm otherwise. A second constraint is operator coverage. The README's own news section points readers to the dev branch "for new latest features on quantum layers and quantum algorithms." That sentence is a signal that the main branch lags the research output. If a gate or layer you need is missing, the answer is likely to check dev rather than to expect it in v0.1.8. A third issue is measurement semantics. The analytical expectation path (expval_joint_analytical) exists only on the classical simulator, while the sampling path (expval_joint_sampling) is the one that carries over to real hardware. If your training loop uses the analytical estimator and your deployment uses sampling, you are training against a different objective than you deploy against. That is a real failure mode for hybrid workflows and the README does not flag it as such. Finally, the notebook-heavy repository (Jupyter Notebook is the primary language) means a large share of the practical documentation lives in examples rather than in reference pages. That is fine for learning and awkward for looking up a function signature.
TorchQuantum against PennyLane: graph-first versus device-first
The README names Qiskit and PennyLane as the comparison points and lists four differences. The most structural one is the dynamic computation graph. In TorchQuantum the circuit state is a tensor that participates in autograd directly, so a backward pass through the expectation value is a normal PyTorch backward call, as the README's expval[0].backward() followed by op.params.grad shows. PennyLane's approach is built around differentiable quantum functions with device abstractions and a plugin interface to many backends, and Qiskit's is built around circuit objects and transpilation to hardware. The practical difference is where the abstraction sits. TorchQuantum optimizes for the case where the simulator is the primary compute substrate and the model is a PyTorch module; PennyLane optimizes for the case where you want one interface across many devices and differentiation methods. If you are already inside a PyTorch training script with a DataLoader and an optimizer, TorchQuantum removes a translation layer that PennyLane's device model reintroduces. If you need to target several hardware vendors through one API, that translation layer is the feature, not the cost. The README also notes TorchQuantum is integrated into the PyTorch Ecosystem and the IBM Qiskit Ecosystem, so the Qiskit relationship is complementary rather than purely competitive: there is an example for converting tq circuits to Qiskit, which is the intended path from simulated training to hardware execution.
Maintenance, licence and what the release cadence tells you
The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is a permissive licence and it is the same one used by much of the PyTorch ecosystem, so there is no copyleft obligation to reason about. This is not legal advice; check the LICENSE file in the repository for the exact text. On maintenance: releases are sparse. v0.1.6 and v0.1.7 landed five days apart in March 2023, and v0.1.8 arrived in February 2024, roughly eleven months later. The repository metadata shows a recent push to main, and the README directs active development to the dev branch. The pattern is a research project that ships when there is something to ship, with the dev branch absorbing ongoing work. For an engineer deciding whether to adopt, that means the upgrade path is not a stream of patch releases. You should expect to pin a commit or a release tag, and to review the diff yourself when you move. The README also points to a Slack channel for "real time support" and to GitHub Issues, which is the realistic support model for a lab project: responsive maintainers, no commercial SLA. Budget for the possibility that you fix a bug yourself or work around it.
Who should adopt it, and what to check before you do
The fit is a research group or an engineer doing quantum machine learning experiments where the ansatz has trainable parameters, the dataset is classical, and the training loop is PyTorch. The mnist, quanvolution, quantum_kernel_method and regression examples are the entry points the README recommends for that work. The fit is weaker for anyone whose primary requirement is breadth of gate support, pulse-level control, or a hardware-first workflow. For those, the honest answer from the available material is that TorchQuantum is not the tool, and the README's own "coming soon" note on pulse simulation is the clearest evidence. A second group that should hesitate is anyone who needs a stable API across a multi-year project: pre-1.0 version numbers plus a dev branch carrying the newest features is a recipe for churn. Before adopting, verify the CUDA and PyTorch version combination in your environment against what the editable install pulls in, confirm the specific gates your ansatz needs exist in the released operator set rather than only on dev, and decide up front whether you will train with the analytical expectation estimator or the sampling one, because only the sampling estimator transfers to real hardware. The README's converter_tq_qiskit example is the path to check if hardware execution is the end goal.
Editorial conclusion
Adopt TorchQuantum if your work is parameterized circuit training on a classical simulator and you want the optimizer, loss and gradient machinery to be ordinary PyTorch. Do not adopt it if you need pulse-level control today, a broad gate set, or a hardware-first workflow where the device is the primary target rather than the simulator. Before committing, verify three things in your own environment: that the pinned PyTorch version still builds with your CUDA toolkit, that the gate you need exists in torchquantum/operator rather than only in the dev branch, and that the Qiskit conversion path in examples/converter_tq_qiskit covers the observables you intend to measure on hardware.
Community notes