⚛️ Quantaflow Demo¶

Build quantum circuits once. Run them anywhere.

This notebook demonstrates the core features of Quantaflow — a framework-neutral quantum computing library by Northstar Corporation.

In [1]:
!pip install quantaflow -q
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/57.2 kB ? eta -:--:--
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 57.2/57.2 kB 4.4 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5.3/5.3 MB 57.7 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 935.6/935.6 kB 46.5 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.9/8.9 MB 94.7 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12.4/12.4 MB 81.8 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.5/2.5 MB 82.6 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.2/2.2 MB 81.4 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 54.5/54.5 kB 4.2 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 167.9/167.9 kB 12.6 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.8/8.8 MB 82.4 MB/s eta 0:00:00

1. Hello Quantum — Your First Circuit¶

In [2]:
from quantaflow import Circuit
from quantaflow.backends import PennyLaneBackend, QiskitBackend

# Build a Bell circuit: (|00⟩ + |11⟩) / √2
qc = Circuit(2)
qc.h(0)           # Hadamard on qubit 0
qc.cx(0, 1)       # CNOT: entangle qubits
qc.measure_all()   # Measure all qubits

print(qc.draw())
q0: ─H────●────M───
q1: ──────X────M───

2. Run on Both Backends — Same Circuit, Zero Changes¶

In [3]:
# Run on PennyLane
pl_result = PennyLaneBackend().run(qc, shots=2000)
print("PennyLane:")
print(f"  Counts:        {pl_result.counts}")
print(f"  Probabilities: { {k: round(v, 3) for k, v in pl_result.probabilities.items()} }")
print(f"  Most common:   {pl_result.most_common(1)}")
print()

# Run on Qiskit — exact same circuit
qi_result = QiskitBackend().run(qc, shots=2000)
print("Qiskit:")
print(f"  Counts:        {qi_result.counts}")
print(f"  Probabilities: { {k: round(v, 3) for k, v in qi_result.probabilities.items()} }")
print(f"  Most common:   {qi_result.most_common(1)}")
/usr/local/lib/python3.12/dist-packages/pennylane/devices/device_api.py:201: PennyLaneDeprecationWarning: Setting shots on device is deprecated. Please use the `set_shots` transform on the respective QNode instead.
  warnings.warn(
PennyLane:
  Counts:        {'00': 1007, '01': 0, '10': 0, '11': 993}
  Probabilities: {'00': 0.503, '01': 0.0, '10': 0.0, '11': 0.496}
  Most common:   [('00', 1007)]

Qiskit:
  Counts:        {'00': 1010, '11': 990}
  Probabilities: {'00': 0.505, '11': 0.495}
  Most common:   [('00', 1010)]

3. Visualize Results¶

In [4]:
pl_result.plot_histogram(title="Bell State — PennyLane")
Out[4]:
No description has been provided for this image
In [5]:
qi_result.plot_probabilities(title="Bell State — Qiskit")
Out[5]:
No description has been provided for this image

4. Matplotlib Circuit Drawing¶

In [6]:
import math

fancy = Circuit(3)
fancy.h(0)
fancy.cx(0, 1)
fancy.ccx(0, 1, 2)
fancy.rx(0, math.pi / 4)
fancy.swap(1, 2)
fancy.crz(0, 1, math.pi / 2)
fancy.u3(2, 1.0, 2.0, 3.0)
fancy.measure_all()

print("ASCII:")
print(fancy.draw())
print(f"\nDepth: {fancy.depth} | Gates: {fancy.gate_count} | Ops: {fancy.count_ops()}")
ASCII:
q0: ─H────●────●────Rx(0.79)────────────●──────────────────────────────M───
q1: ──────X────●────────────────×────Rz(1.57)──────────────────────────M───
q2: ───────────X────────────────×────────────────U3(1.00,2.00,3.00)────M───

Depth: 5 | Gates: 7 | Ops: {'h': 1, 'cx': 1, 'ccx': 1, 'rx': 1, 'swap': 1, 'crz': 1, 'u3': 1}
In [7]:
fancy.draw('mpl')
Out[7]:
No description has been provided for this image

5. All 18 Gates in Action¶

In [8]:
import math

demo = Circuit(3)

# Pauli gates
demo.h(0).x(1).y(2).z(0)

# Phase gates
demo.s(0).t(1).sdg(0).tdg(1)

# Rotation gates
demo.rx(0, math.pi/4).ry(1, math.pi/3).rz(2, math.pi/6)

# Multi-qubit gates
demo.cx(0, 1).swap(1, 2).ccx(0, 1, 2)

# Controlled rotations
demo.crx(0, 1, 0.5).cry(1, 2, 0.7).crz(0, 2, 0.3)

# Universal gate
demo.u3(0, 1.0, 2.0, 3.0)

demo.measure_all()

print(f"Gates: {demo.gate_count}")
print(f"Ops breakdown: {demo.count_ops()}")
print(f"Depth: {demo.depth}")

result = PennyLaneBackend().run(demo, shots=1000)
print(f"\nTop 5 outcomes: {result.most_common(5)}")
result.plot_histogram(title="All 18 Gates Circuit")
Gates: 18
Ops breakdown: {'h': 1, 'x': 1, 'y': 1, 'z': 1, 's': 1, 't': 1, 'sdg': 1, 'tdg': 1, 'rx': 1, 'ry': 1, 'rz': 1, 'cx': 1, 'swap': 1, 'ccx': 1, 'crx': 1, 'cry': 1, 'crz': 1, 'u3': 1}
Depth: 10

Top 5 outcomes: [('110', 512), ('111', 374), ('010', 49), ('011', 34), ('101', 14)]
Out[8]:
No description has been provided for this image

6. Framework Interop — Drop Into Qiskit or PennyLane Anytime¶

In [9]:
# Build in Quantaflow
qc = Circuit(2)
qc.h(0).cx(0, 1).measure_all()

# Convert to Qiskit and use Qiskit's visualization
qiskit_qc = qc.to_qiskit()
print("Qiskit circuit:")
print(qiskit_qc.draw())
print(f"\nQiskit depth: {qiskit_qc.depth()}")
print(f"Qiskit gate count: {qiskit_qc.size()}")
Qiskit circuit:
     ┌───┐     ┌─┐   
q_0: ┤ H ├──■──┤M├───
     └───┘┌─┴─┐└╥┘┌─┐
q_1: ─────┤ X ├─╫─┤M├
          └───┘ ║ └╥┘
c: 2/═══════════╩══╩═
                0  1 

Qiskit depth: 3
Qiskit gate count: 4
In [10]:
# Import a circuit FROM Qiskit
from qiskit import QuantumCircuit

# Build in pure Qiskit
qiskit_ghz = QuantumCircuit(3)
qiskit_ghz.h(0)
qiskit_ghz.cx(0, 1)
qiskit_ghz.cx(1, 2)

# Import into Quantaflow
ghz = Circuit.from_qiskit(qiskit_ghz)
ghz.measure_all()

print("Imported from Qiskit:")
print(ghz.draw())

# Run on PennyLane (!) — circuit came from Qiskit but runs anywhere
result = PennyLaneBackend().run(ghz, shots=1000)
print(f"\nGHZ state results: {result.counts}")
result.plot_histogram(title="GHZ State (built in Qiskit, ran on PennyLane)")
Imported from Qiskit:
q0: ─H────●─────────M───
q1: ──────X────●────M───
q2: ───────────X────M───

GHZ state results: {'000': 496, '001': 0, '010': 0, '011': 0, '100': 0, '101': 0, '110': 0, '111': 504}
Out[10]:
No description has been provided for this image
In [11]:
# Import from PennyLane
import pennylane as qml

with qml.tape.QuantumTape() as tape:
    qml.Hadamard(wires=0)
    qml.CNOT(wires=[0, 1])
    qml.Toffoli(wires=[0, 1, 2])

qf = Circuit.from_pennylane(tape)
qf.measure_all()

print("Imported from PennyLane:")
print(qf.draw())

# Run on Qiskit (!) — circuit came from PennyLane but runs anywhere
result = QiskitBackend().run(qf, shots=1000)
print(f"\nResults: {result.counts}")
Imported from PennyLane:
q0: ─H────●────●────M───
q1: ──────X────●────M───
q2: ───────────X────M───

Results: {'111': 491, '000': 509}

7. Circuit Manipulation¶

In [12]:
# Build a circuit
qc = Circuit(2)
qc.h(0).s(0).cx(0, 1)

print("Original:")
print(qc.draw())

# Get the inverse (adjoint)
inv = qc.inverse()
print("\nInverse (adjoint):")
print(inv.draw())

# Copy and modify
copy = qc.copy()
copy.t(1).measure_all()
print("\nCopy (modified):")
print(copy.draw())

print(f"\nOriginal has {len(qc)} gates, copy has {len(copy)} gates")
Original:
q0: ─H────S────●───
q1: ───────────X───

Inverse (adjoint):
q0: ─●────Sdg────H───
q1: ─X───────────────

Copy (modified):
q0: ─H────S────●─────────M───
q1: ───────────X────T────M───

Original has 3 gates, copy has 4 gates

🚀 What's Next?¶

Version What's Coming
v0.0.3 IBM Quantum hardware, Amazon Braket, noise models
v0.0.4 VQE, QAOA algorithms, parameter sweeps
v0.0.5 Transpiler, plugin system, benchmarking

⭐ Star us on GitHub: github.com/NorthstarsIndustries/quantaflow

📦 PyPI: pypi.org/project/quantaflow