Skip to main content

Framework-neutral quantum computing library. Build once, run on PennyLane, Qiskit, and more.

Project description

⚛️ Quantaflow

Build quantum circuits once. Run them anywhere.

CI PyPI Python License


Quantaflow is an open-source Python library for building and running quantum programs with a single, framework-neutral workflow. It gives you a simple circuit and program model that isn't tied to any one ecosystem, then lets you execute the same code on multiple backends — starting with PennyLane and Qiskit — while returning consistent, NumPy-friendly results.

Quantaflow is designed to remove the usual "plumbing" (rewriting circuits, swapping execution APIs, normalizing outputs, and managing run metadata) so you can focus on experiments and algorithms, not framework glue.

Status: v0.0.2 — Alpha release. 18 gates, circuit visualization, framework interop, and two simulator backends.


Table of Contents


Why Quantaflow?

If you've ever worked with quantum computing frameworks, you know the pain:

Problem Without Quantaflow With Quantaflow
Framework lock-in Rewrite circuits for each backend Write once, run anywhere
Different result formats Parse each framework's output differently Consistent Result object everywhere
Setup boilerplate Device creation, transpilation, measurement setup One-liner: backend.run(circuit, shots=1000)
Comparing backends Separate scripts for each Same circuit, swap one line
Visualization Learn each framework's plotting API circuit.draw() and result.plot_histogram()
Using both ecosystems Maintain parallel codebases circuit.to_qiskit() / circuit.to_pennylane()

Quantaflow sits between your algorithm and the execution layer, handling the translation so you don't have to.


Features

✅ In v0.0.2 (Current)

  • 18 quantum gates — H, X, Y, Z, S, T, S†, T†, RX, RY, RZ, CX, SWAP, CCX (Toffoli), CRX, CRY, CRZ, U3
  • Circuit visualization — ASCII text draw() and matplotlib draw('mpl')
  • Result visualizationplot_histogram() and plot_probabilities() with matplotlib
  • Framework interopto_qiskit(), to_pennylane(), from_qiskit(), from_pennylane()
  • Circuit introspectiondepth, gate_count, count_ops(), inverse(), copy()
  • PennyLane backenddefault.qubit simulator (configurable device)
  • Qiskit backendAerSimulator with automatic fallback
  • Consistent Result object.counts, .probabilities, .most_common(), .metadata
  • Fluent API — chainable gate calls
  • 89 tests — comprehensive test suite including cross-backend validation

🚧 Coming Soon

  • IBM Quantum hardware — v0.0.3
  • Amazon Braket backend — v0.0.3
  • Noise models and error mitigation — v0.0.3
  • VQE & QAOA algorithms — v0.0.4
  • Parameter sweeps and batching — v0.0.4
  • Transpiler passes — v0.0.5
  • Plugin system — v0.0.5

See the full Roadmap →


Installation

Install

pip install quantaflow

That's it. One command gives you everything — both backends (PennyLane + Qiskit), visualization (matplotlib), and all 18 gates.

Upgrade

pip install --upgrade quantaflow

Development setup (with conda)

# Clone the repo
git clone https://github.com/NorthstarsIndustries/quantaflow.git
cd quantaflow

# Create conda environment
conda env create -f environment.yml
conda activate quantaflow-dev

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest -q

Requirements

  • Python 3.10, 3.11, or 3.12
  • All dependencies are installed automatically: NumPy, PennyLane, Qiskit, Qiskit Aer, matplotlib

Quick Start

from quantaflow import Circuit
from quantaflow.backends import PennyLaneBackend

# 1. Build a circuit
qc = Circuit(2)
qc.h(0)          # Hadamard on qubit 0
qc.cx(0, 1)      # CNOT: entangle qubits 0 and 1
qc.measure_all()  # Measure in computational basis

# 2. Run it
backend = PennyLaneBackend()
result = backend.run(qc, shots=1000)

# 3. Get results
print(result.counts)         # {'00': 503, '11': 497}
print(result.probabilities)  # {'00': 0.503, '11': 0.497}
print(result.most_common(1)) # [('00', 503)]

# 4. Visualize
print(qc.draw())             # ASCII circuit diagram
result.plot_histogram()       # matplotlib bar chart

The Bell Experiment

This is the copy-paste example that should just work. It creates a Bell state and runs it on both backends to show they produce equivalent results:

from quantaflow import Circuit
from quantaflow.backends import PennyLaneBackend, QiskitBackend

# Build a Bell circuit: (|00⟩ + |11⟩) / √2
qc = Circuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()

# See what you built
print(qc.draw())
# q0: ─[H]─●───[M]─
# q1: ─────X───[M]─

# Run on PennyLane
pl_result = PennyLaneBackend().run(qc, shots=2000)
print(f"PennyLane: {pl_result.counts}")
print(f"  P(00) = {pl_result.probabilities['00']:.3f}")
print(f"  P(11) = {pl_result.probabilities['11']:.3f}")

print()

# Run on Qiskit — same circuit, no changes needed
qi_result = QiskitBackend().run(qc, shots=2000)
print(f"Qiskit:    {qi_result.counts}")
print(f"  P(00) = {qi_result.probabilities['00']:.3f}")
print(f"  P(11) = {qi_result.probabilities['11']:.3f}")

# Both backends produce ~50/50 split between |00⟩ and |11⟩
# Exactly what you'd expect from a Bell state!

Expected output:

PennyLane: {'00': 1012, '11': 988}
  P(00) = 0.506
  P(11) = 0.494

Qiskit:    {'00': 987, '11': 1013}
  P(00) = 0.494
  P(11) = 0.506

Visualization

Quantaflow provides built-in visualization for both circuits and results.

Circuit Drawing

from quantaflow import Circuit

qc = Circuit(3)
qc.h(0)
qc.cx(0, 1)
qc.ccx(0, 1, 2)
qc.measure_all()

# ASCII text drawing (no extra dependencies)
print(qc.draw())

# Matplotlib drawing (requires quantaflow[visualization])
fig = qc.draw('mpl')
fig.savefig('my_circuit.png')

Result Plotting

from quantaflow import Circuit
from quantaflow.backends import PennyLaneBackend

qc = Circuit(2)
qc.h(0).cx(0, 1).measure_all()
result = PennyLaneBackend().run(qc, shots=1000)

# Bar chart of measurement counts
result.plot_histogram(title="Bell State Counts")

# Bar chart of probabilities
result.plot_probabilities(title="Bell State Probabilities")

# Save directly to file
result.plot_histogram(filename="histogram.png")

Framework Interop

The killer feature of Quantaflow: seamlessly switch between frameworks. Build your circuit in Quantaflow, then drop into Qiskit or PennyLane whenever you need framework-specific tools.

Convert to Qiskit

from quantaflow import Circuit

qc = Circuit(2)
qc.h(0).cx(0, 1).measure_all()

# Convert to Qiskit QuantumCircuit
qiskit_qc = qc.to_qiskit()

# Now use ANY Qiskit feature:
qiskit_qc.draw('mpl')           # Qiskit's rich visualization
# qiskit_qc.decompose()         # Qiskit's decomposition
# transpile(qiskit_qc, backend) # Qiskit's transpiler

Convert to PennyLane

from quantaflow import Circuit

qc = Circuit(2)
qc.h(0).cx(0, 1).measure_all()

# Get an executable PennyLane QNode
qnode = qc.to_pennylane(device="default.qubit", shots=1000)
result = qnode()  # Execute in PennyLane

# Or get a gate-applying function for custom workflows
gate_fn = qc.to_pennylane()

Import from Other Frameworks

from quantaflow import Circuit

# Import a Qiskit circuit
from qiskit import QuantumCircuit
qiskit_qc = QuantumCircuit(2)
qiskit_qc.h(0)
qiskit_qc.cx(0, 1)
qf_circuit = Circuit.from_qiskit(qiskit_qc)

# Import a PennyLane tape
import pennylane as qml
with qml.tape.QuantumTape() as tape:
    qml.Hadamard(wires=0)
    qml.CNOT(wires=[0, 1])
qf_circuit = Circuit.from_pennylane(tape)

# Now run on any backend!
from quantaflow.backends import PennyLaneBackend, QiskitBackend
qf_circuit.measure_all()
result = PennyLaneBackend().run(qf_circuit, shots=1000)

API Reference

Circuit

from quantaflow import Circuit

Circuit(num_qubits: int)

Create a new quantum circuit.

Property / Method Description
qc.num_qubits Number of qubits in the circuit
qc.ops List of operations (read-only)
qc.measured Whether measure_all() has been called
len(qc) Number of gate operations
qc.depth Circuit depth (max ops on any wire)
qc.gate_count Total number of gate operations
qc.count_ops() Dict of gate counts, e.g. {"h": 2, "cx": 1}
qc.inverse() New circuit with reversed and inverted operations
qc.copy() Deep copy of the circuit
qc.draw(output='text') ASCII circuit diagram (str)
qc.draw(output='mpl') Matplotlib Figure of the circuit
qc.to_qiskit() Convert to qiskit.QuantumCircuit
qc.to_pennylane(device=..., shots=...) Convert to PennyLane QNode or gate function
Circuit.from_qiskit(qc) Create from a Qiskit QuantumCircuit
Circuit.from_pennylane(tape) Create from a PennyLane tape

Gate Methods

All gate methods return self for chaining:

qc = Circuit(3)
qc.h(0).cx(0, 1).rx(2, 3.14).swap(0, 1)  # Fluent API
Method Description Parameters
qc.h(wire) Hadamard gate
qc.x(wire) Pauli-X (NOT) gate
qc.y(wire) Pauli-Y gate
qc.z(wire) Pauli-Z gate
qc.s(wire) S gate (√Z)
qc.t(wire) T gate (⁴√Z)
qc.sdg(wire) S† (adjoint of S)
qc.tdg(wire) T† (adjoint of T)
qc.rx(wire, angle) X-rotation angle in radians
qc.ry(wire, angle) Y-rotation angle in radians
qc.rz(wire, angle) Z-rotation angle in radians
qc.u3(wire, θ, φ, λ) Universal single-qubit 3 angles
qc.cx(control, target) CNOT gate Two distinct wires
qc.swap(wire0, wire1) SWAP gate Two distinct wires
qc.ccx(c0, c1, target) Toffoli (CCX) gate Three distinct wires
qc.crx(ctrl, tgt, angle) Controlled RX Two wires + angle
qc.cry(ctrl, tgt, angle) Controlled RY Two wires + angle
qc.crz(ctrl, tgt, angle) Controlled RZ Two wires + angle
qc.measure_all() Measure all qubits Locks circuit

Backends

from quantaflow.backends import PennyLaneBackend, QiskitBackend

PennyLaneBackend(device="default.qubit")

Method Description
backend.run(circuit, shots=1024) Execute circuit, return Result
backend.name "pennylane/default.qubit"

QiskitBackend()

Automatically selects AerSimulator if available, otherwise falls back.

Method Description
backend.run(circuit, shots=1024) Execute circuit, return Result
backend.name "qiskit/AerSimulator"

Result

from quantaflow import Result
Property / Method Type Description
result.counts dict[str, int] Raw counts, e.g. {"00": 503, "11": 497}
result.probabilities dict[str, float] Normalized probabilities
result.shots int Total shots (sum of counts)
result.metadata dict Backend name, shots, quantaflow version
result.most_common(n) list[tuple] Top n results by count
result.plot_histogram() Figure matplotlib bar chart of counts
result.plot_probabilities() Figure matplotlib bar chart of probabilities

Supported Gates

Gate Type Qubits Parameters Description
h Clifford 1 Hadamard: creates superposition
x Pauli 1 Bit flip (NOT gate)
y Pauli 1 Pauli-Y gate
z Pauli 1 Phase flip (Pauli-Z)
s Phase 1 S gate (√Z, π/2 phase)
t Phase 1 T gate (⁴√Z, π/4 phase)
sdg Phase 1 S† (adjoint of S)
tdg Phase 1 T† (adjoint of T)
rx Rotation 1 angle Rotation around X-axis
ry Rotation 1 angle Rotation around Y-axis
rz Rotation 1 angle Rotation around Z-axis
u3 Universal 1 θ, φ, λ Universal single-qubit gate
cx Entangling 2 Controlled-NOT (CNOT)
swap Entangling 2 SWAP gate
ccx Entangling 3 Toffoli (controlled-controlled-NOT)
crx Controlled 2 angle Controlled X-rotation
cry Controlled 2 angle Controlled Y-rotation
crz Controlled 2 angle Controlled Z-rotation

Roadmap

Version Codename Highlights
v0.0.1 Hello Quantum Circuit builder, PennyLane + Qiskit backends, Result object
v0.0.2 The Vision Release 18 gates, visualization, framework interop, circuit introspection
v0.0.3 Real Hardware IBM Quantum, Amazon Braket, noise models, error mitigation
v0.0.4 Algorithms VQE, QAOA, parameter sweeps, batching, caching
v0.0.5 Production Ready Transpiler, plugins, benchmarking, full docs

See the full Roadmap → for detailed feature plans.


Contributing

We welcome contributions from the quantum computing community! Please read our:


License

Copyright (c) 2026 Northstar Corporation. All rights reserved.

Licensed under the Apache License, Version 2.0.


Built with ❤️ by Northstar Corporation

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

quantaflow-0.0.2.tar.gz (31.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

quantaflow-0.0.2-py3-none-any.whl (27.4 kB view details)

Uploaded Python 3

File details

Details for the file quantaflow-0.0.2.tar.gz.

File metadata

  • Download URL: quantaflow-0.0.2.tar.gz
  • Upload date:
  • Size: 31.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for quantaflow-0.0.2.tar.gz
Algorithm Hash digest
SHA256 457336f26ac944e8c08f26080de41b3dba247a9f2fa7558cd5754b05459ecf4d
MD5 2f82f9337ba3057379539dbc8ad0bc6e
BLAKE2b-256 2a001bb834c24c4c144c70bfe7330267e5a2059cbafc882887ba702ae8f2ac05

See more details on using hashes here.

Provenance

The following attestation bundles were made for quantaflow-0.0.2.tar.gz:

Publisher: publish.yml on NorthstarsIndustries/quantaflow

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file quantaflow-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: quantaflow-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 27.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for quantaflow-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 9685b9a8ecefa3cb6efd64a8ff87b0a9bfd88dd6d92b6e4880283ff685352b6e
MD5 3df2422f3ca51adefc922d80c16406c4
BLAKE2b-256 187f8f1d5afcbda84a32b343849ee0cf11795ff0fed0a77464efb06d566791b0

See more details on using hashes here.

Provenance

The following attestation bundles were made for quantaflow-0.0.2-py3-none-any.whl:

Publisher: publish.yml on NorthstarsIndustries/quantaflow

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page