Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

QCQI — Chapter 1: Overview & Postulates

Goal: solidify the four postulates with small, runnable demos across multiple frameworks (non‑IBM by default).

Set backend below to one of: cirq, pennylane, braket, pyquil, qiskit.

# Backend selector
backend = "pennylane"  # change: "pennylane", "braket", "pyquil", "qiskit"
print("Selected backend:", backend)
# Optional installs (if needed)
# !pip install cirq pennylane amazon-braket-sdk pyquil qiskit qiskit-aer
Selected backend: pennylane

Utilities

import numpy as np
def probs_from_state(psi):
    p = np.abs(psi.flatten())**2
    return p/p.sum()
def ket0(): return np.array([[1],[0]], dtype=complex)
def ket1(): return np.array([[0],[1]], dtype=complex)
X = np.array([[0,1],[1,0]], dtype=complex)
Y = np.array([[0,-1j],[1j,0]], dtype=complex)
Z = np.array([[1,0],[0,-1]], dtype=complex)
H = (1/np.sqrt(2))*np.array([[1,1],[1,-1]], dtype=complex)

Postulate II: Unitary evolution demo

# Rotate |0> by H, then Rz(pi/2), then H; check final probabilities
def Rz(theta):
    return np.array([[np.exp(-1j*theta/2),0],[0,np.exp(1j*theta/2)]], dtype=complex)
psi = ket0()
U = H @ Rz(np.pi/2) @ H
psi2 = U @ psi
print("probs(Z):", probs_from_state(psi2))
probs(Z): [0.5 0.5]

Postulate III: Measurement and a simple POVM

# A two-outcome POVM defined by effects E0, E1=I-E0
I = np.eye(2, dtype=complex)
v = np.array([[np.sqrt(0.7)],[0]], dtype=complex)
E0 = v @ v.conj().T          # rank-1 effect with weight 0.7 along |0>
E1 = I - E0
def meas_povm(rho, effects):
    return [float(np.real(np.trace(E @ rho))) for E in effects]
rho = ket0() @ ket0().conj().T
print("POVM probs:", meas_povm(rho, [E0,E1]))
POVM probs: [0.7000000000000001, 0.29999999999999993]

Postulate IV: Composition and reduced states

# Build a Bell state and compute reduced density matrix of qubit A
psi = (1/np.sqrt(2))*np.array([[1,0,0,1]], dtype=complex).T  # |00> + |11>
rho = psi @ psi.conj().T
# partial trace over qubit B
rhoA = np.array([[rho[0,0]+rho[1,1], rho[0,2]+rho[1,3]],
                 [rho[2,0]+rho[3,1], rho[2,2]+rho[3,3]]], dtype=complex)
print("rho_A=", np.round(rhoA, 3))
rho_A= [[0.5+0.j 0. +0.j]
 [0. +0.j 0.5+0.j]]

Framework examples

Cirq: H + measurement

if backend == "cirq":
    import cirq
    q = cirq.LineQubit(0)
    c = cirq.Circuit(cirq.H(q), cirq.measure(q, key="m"))
    print(c)
    sim = cirq.Simulator()
    res = sim.run(c, repetitions=1000)
    print(dict(res.histogram(key="m")))
0: ───H───M('m')───
{1: 485, 0: 515}

PennyLane: POVM via projectors

if backend == "pennylane":
    import pennylane as qml, numpy as np
    dev = qml.device("default.qubit", wires=1, shots=1000)
    @qml.qnode(dev)
    def circuit():
        # prepare |0>, apply H then RZ
        qml.H(0); qml.RZ(np.pi/2, 0)
        return qml.sample(qml.PauliZ(0))
    s = circuit()
    zeros = int(((s+1)/2 == 0).sum()); ones = int(((s+1)/2 == 1).sum())
    print({"0": zeros, "1": ones})
{'0': 502, '1': 498}

Braket: local simulator

if backend == "braket":
    from braket.circuits import Circuit
    from braket.devices import LocalSimulator
    circ = Circuit().h(0).rz(0, np.pi/2).probability()
    dev = LocalSimulator()
    res = dev.run(circ, shots=1000).result()
    print(res.values[0])  # probabilities [p0, p1]
[0.513 0.487]

PyQuil: QVM example

if backend == "pyquil":
    from pyquil import Program
    from pyquil.gates import H, RZ, MEASURE
    from pyquil.api import get_qc
    p = Program()
    ro = p.declare("ro", "BIT", 1)
    p += H(0); p += RZ(np.pi/2, 0); p += MEASURE(0, ro[0])
    qc = get_qc("1q-qvm")
    res = qc.run(p.wrap_in_numshots_loop(1000))
    bits = res.get_register_map()['ro']
    import numpy as np
    print({"0": int((bits==0).sum()), "1": int((bits==1).sum())})
{'0': 516, '1': 484}

Qiskit: Aer simulator (optional)

if backend == "qiskit":
    from qiskit import QuantumCircuit
    from qiskit_aer import AerSimulator
    qc = QuantumCircuit(1,1)
    qc.h(0); qc.rz(np.pi/2, 0); qc.measure(0,0)
    sim = AerSimulator()
    res = sim.run(qc, shots=1000).result().get_counts()
    print(res)
{'0': 472, '1': 528}

Exercises

  1. Implement a three-outcome POVM on a single qubit and verify mp(m)=1\sum_m p(m)=1.

  2. Prepare ψ(θ)=cosθ20+sinθ21\ket{\psi(\theta)}=\cos\frac\theta2\ket{0}+\sin\frac\theta2\ket{1} and plot p(1)p(1) vs θ\theta.

  3. Build Φ=(0011)/2\ket{\Phi^-}=(\ket{00}-\ket{11})/\sqrt2 and verify ρA=I/2\rho_A=I/2.