Which framework should I use?

Quick Comparison

Framework Primary use case Hardware access Differentiable Language Best for
Qiskit General purpose IBM Quantum (free) Via Qiskit Machine Learning Python Beginners, IBM hardware
Cirq Hardware research Google (research access) Partial Python Google hardware, low-level control
PennyLane QML / hybrid Any (plugin system) Yes (parameter-shift) Python Machine learning, research
Braket Cloud multi-hardware IonQ, Rigetti, QuEra, IQM No Python Production, AWS users
PyQuil Rigetti hardware Rigetti QCS No Python Rigetti hardware
tket Compilation / optimization Any (backend plugins) No Python / C++ Circuit optimization, hardware-agnostic
Q# Algorithms / research Azure Quantum No Q# (own lang) Microsoft ecosystem, resource estimation

Compare Syntax

Installation

Qiskit

pip install qiskit qiskit-aer qiskit-ibm-runtime

Cirq

pip install cirq

Braket

pip install amazon-braket-sdk amazon-braket-default-simulator

PyQuil

pip install pyquil

tket

pip install pytket pytket-qiskit

Q#

pip install qsharp

Bell State (H + CNOT)

Qiskit

from qiskit import QuantumCircuit

qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])

Cirq

import cirq

q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit([
    cirq.H(q0),
    cirq.CNOT(q0, q1),
    cirq.measure(q0, q1, key='m'),
])

PennyLane

import pennylane as qml

dev = qml.device('default.qubit', wires=2)

@qml.qnode(dev)
def bell():
    qml.Hadamard(wires=0)
    qml.CNOT(wires=[0, 1])
    return qml.probs(wires=[0, 1])

Braket

from braket.circuits import Circuit

circuit = Circuit().h(0).cnot(0, 1)

PyQuil

from pyquil import Program
from pyquil.gates import H, CNOT, MEASURE

p = Program()
ro = p.declare('ro', 'BIT', 2)
p += H(0)
p += CNOT(0, 1)
p += MEASURE(0, ro[0])
p += MEASURE(1, ro[1])

tket

from pytket import Circuit

circ = Circuit(2, 2)
circ.H(0)
circ.CX(0, 1)
circ.measure_all()

Q#

operation BellState() : (Result, Result) {
    use (q0, q1) = (Qubit(), Qubit());
    H(q0);
    CNOT(q0, q1);
    return (MResetZ(q0), MResetZ(q1));
}

Run & Get Measurement Counts

Qiskit

from qiskit_aer import AerSimulator
from qiskit import transpile

sim = AerSimulator()
result = sim.run(transpile(qc, sim), shots=1000).result()
print(result.get_counts())

Cirq

sim = cirq.Simulator()
result = sim.run(circuit, repetitions=1000)
print(result.histogram(key='m'))

PennyLane

# probs() returns exact distribution
# For shot-based counts:
@qml.qnode(dev, shots=1000)
def bell_shots():
    qml.Hadamard(wires=0)
    qml.CNOT(wires=[0, 1])
    return qml.counts(wires=[0, 1])

print(bell_shots())

Braket

from braket.devices import LocalSimulator

device = LocalSimulator()
result = device.run(circuit, shots=1000).result()
print(result.measurement_counts)

PyQuil

from pyquil import get_qc
from collections import Counter

p.wrap_in_numshots_loop(1000)
qc = get_qc('2q-qvm')
results = qc.run(p).readout_data.get('ro')
print(Counter(map(tuple, results)))

tket

from pytket.extensions.qiskit import AerBackend

backend = AerBackend()
compiled = backend.get_compiled_circuit(circ)
result = backend.run_circuit(compiled, n_shots=1000)
print(result.get_counts())

Q#

import qsharp

results = [qsharp.eval("""
    use (q0, q1) = (Qubit(), Qubit());
    H(q0); CNOT(q0, q1);
    let r = (M(q0), M(q1));
    ResetAll([q0, q1]); r
""") for _ in range(1000)]

from collections import Counter
print(Counter(results))

Parameterised Single-Qubit Rotation (Ry)

Qiskit

from qiskit.circuit import Parameter

theta = Parameter('theta')
qc = QuantumCircuit(1)
qc.ry(theta, 0)
bound = qc.assign_parameters({theta: 1.5708})

Cirq

import sympy

theta = sympy.Symbol('theta')
q = cirq.LineQubit(0)
circuit = cirq.Circuit(cirq.ry(theta)(q))

# Resolve
resolver = cirq.ParamResolver({'theta': 1.5708})
resolved = cirq.resolve_parameters(circuit, resolver)

PennyLane

import pennylane as qml
from pennylane import numpy as np

@qml.qnode(dev)
def rotation(theta):
    qml.RY(theta, wires=0)
    return qml.expval(qml.PauliZ(0))

# Also: gradient is free
grad = qml.grad(rotation)
print(grad(np.array(1.5708, requires_grad=True)))

Braket

from braket.circuits import Circuit, FreeParameter

theta = FreeParameter('theta')
circuit = Circuit().ry(0, theta)

result = device.run(
    circuit, shots=1000, inputs={'theta': 1.5708}
).result()

PyQuil

from pyquil import Program
from pyquil.gates import RY, MEASURE

p = Program()
angle = p.declare('angle', 'REAL', 1)
ro = p.declare('ro', 'BIT', 1)
p += RY(angle, 0)
p += MEASURE(0, ro[0])

qc = get_qc('1q-qvm')
result = qc.run(p, memory_map={'angle': [1.5708]})

tket

from pytket.circuit import fresh_symbol
import sympy

theta = fresh_symbol('theta')
circ = Circuit(1)
circ.Ry(theta / sympy.pi, 0)   # tket angles in half-turns

circ.symbol_substitution({theta: 1.5708})

Q#

operation RotateY(theta : Double) : Result {
    use q = Qubit();
    Ry(theta, q);
    return MResetZ(q);
}

// From Python:
// qsharp.eval(f"RotateY({1.5708})")

Get the Statevector

Qiskit

from qiskit.quantum_info import Statevector

sv = Statevector(qc)
print(sv.data)
print(sv.probabilities_dict())

Cirq

sim = cirq.Simulator()
result = sim.simulate(circuit)
print(result.final_state_vector)

PennyLane

@qml.qnode(dev)
def get_state():
    qml.Hadamard(wires=0)
    qml.CNOT(wires=[0, 1])
    return qml.state()

print(get_state())

Braket

# shots=0 returns statevector
result = device.run(circuit, shots=0).result()
print(result.values[0])

PyQuil

from pyquil.api import WavefunctionSimulator

wfs = WavefunctionSimulator()
wf = wfs.wavefunction(p)
print(wf.amplitudes)
print(wf.probabilities())

tket

from pytket.extensions.qiskit import AerStateBackend

backend = AerStateBackend()
state = backend.run_circuit(circ).get_state()
print(state)

Q#

// DumpMachine prints statevector to stdout
import qsharp
qsharp.eval("""
    use q = Qubit();
    H(q);
    Microsoft.Quantum.Diagnostics.DumpMachine();
    Reset(q);
""")

Draw / Visualise the Circuit

Qiskit

print(qc.draw('text'))
qc.draw('mpl')     # matplotlib
qc.draw('latex')   # LaTeX

Cirq

print(circuit)
print(circuit.to_text_diagram())

PennyLane

print(qml.draw(bell)())
qml.draw_mpl(bell)()

Braket

print(circuit)
# ASCII diagram built-in

PyQuil

# PyQuil prints Quil assembly, not diagrams
print(p)
# Use qiskit to visualise via conversion

tket

from pytket.utils import Graph
Graph(circ).get_DAG()  # DAG view
# Or render via qiskit:
from pytket.extensions.qiskit import tk_to_qiskit
tk_to_qiskit(circ).draw('mpl')

Q#

// Q# has no built-in visualiser
// Export to Qiskit via pytket or
// use VS Code Azure Quantum extension
// for circuit preview in the IDE