Note
Go to the end to download the full example code.
The no-cloning theorem: why a fixed unitary can copy a basis, not a state#
Wootters, Zurek, and (independently) Dieks proved that no unitary process
can take an arbitrary, unknown quantum state and produce two independent
copies of it. The proof is a direct consequence of linearity: a unitary
that faithfully clones two particular states must, by linearity, act on
their superposition in a way that is not a faithful copy of that
superposition. This example makes the failure completely explicit with
the simplest possible candidate “cloning machine,” the CNOT gate: it
successfully copies the computational basis states \(\lvert0\rangle\)
and \(\lvert1\rangle\), but applied to a superposition it produces
exactly a Bell state – physicskit.quantum.chapters.entanglement.bell_state() –
rather than two independent copies, entangling the two qubits instead of
cloning either one.
import matplotlib.pyplot as plt
import numpy as np
from physicskit.quantum.chapters.entanglement import bell_state
CNOT as a candidate cloning machine#
CNOT|source>|target=0> flips the target exactly when the source is |1>: CNOT|0>|0>=|0>|0>, CNOT|1>|0>=|1>|1> – both genuine copies, since the target ends up identical to the source in both cases.
CNOT = np.array(
[
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0],
],
dtype=complex,
)
ket0 = np.array([1, 0], dtype=complex)
ket1 = np.array([0, 1], dtype=complex)
def clone_attempt(psi):
"""Apply CNOT to psi (x) |0>, the candidate cloning operation."""
input_state = np.kron(psi, ket0)
return CNOT @ input_state
out0 = clone_attempt(ket0)
out1 = clone_attempt(ket1)
print("CNOT|0>|0> =", np.round(out0.real, 3), " (matches |0>|0>: perfect copy of |0>)")
print("CNOT|1>|0> =", np.round(out1.real, 3), " (matches |1>|1>: perfect copy of |1>)")
CNOT|0>|0> = [1. 0. 0. 0.] (matches |0>|0>: perfect copy of |0>)
CNOT|1>|0> = [0. 0. 0. 1.] (matches |1>|1>: perfect copy of |1>)
The same machine, applied to a superposition#
A faithful clone of |+> = (|0>+|1>)/sqrt(2) would produce the PRODUCT state |+>|+> = (|00>+|01>+|10>+|11>)/2. What CNOT actually produces, by linearity from the two basis results above, is instead exactly a Bell state: entangled, not a pair of independent copies at all.
plus = (ket0 + ket1) / np.sqrt(2)
actual_output = clone_attempt(plus)
would_be_clone = np.kron(plus, plus)
bell = bell_state("phi+")
print(f"\nactual CNOT output on |+>|0>: {np.round(actual_output.real, 4)}")
print(f"a faithful clone would have given: {np.round(would_be_clone.real, 4)}")
print(f"physicskit's own Bell state |phi+>: {np.round(bell.real, 4)}")
print(f"|actual output - Bell state|: {np.linalg.norm(actual_output - bell):.2e} (CNOT produced exactly a Bell state)")
fidelity = np.abs(np.vdot(would_be_clone, actual_output)) ** 2
print(f"\nfidelity between the actual output and a faithful clone: {fidelity:.4f} (far below 1 -- cloning failed)")
actual CNOT output on |+>|0>: [0.7071 0. 0. 0.7071]
a faithful clone would have given: [0.5 0.5 0.5 0.5]
physicskit's own Bell state |phi+>: [0.7071 0. 0. 0.7071]
|actual output - Bell state|: 0.00e+00 (CNOT produced exactly a Bell state)
fidelity between the actual output and a faithful clone: 0.5000 (far below 1 -- cloning failed)
Cloning fidelity across every possible input state#
CNOT clones perfectly only the two states it was “tuned” for (theta=0 and theta=pi below); everywhere else – every unknown superposition an actual cloning machine would need to handle – the fidelity to a faithful copy drops well below 1, vanishing entirely at the equator where the state is an equal superposition.
theta_values = np.linspace(0, np.pi, 200)
fidelities = []
for theta in theta_values:
psi = np.cos(theta / 2) * ket0 + np.sin(theta / 2) * ket1
actual = clone_attempt(psi)
ideal_clone = np.kron(psi, psi)
fidelities.append(np.abs(np.vdot(ideal_clone, actual)) ** 2)
fidelities = np.array(fidelities)
fig, ax = plt.subplots(figsize=(7, 4.5))
ax.plot(np.degrees(theta_values), fidelities, color="firebrick")
ax.axvline(0, color="0.6", ls="--", lw=1)
ax.axvline(180, color="0.6", ls="--", lw=1)
ax.set_xlabel(r"input state angle $\theta$ (degrees), $|\psi\rangle=\cos(\theta/2)|0\rangle+\sin(\theta/2)|1\rangle$")
ax.set_ylabel("cloning fidelity")
ax.set_title("CNOT clones only the two states it was built for -- theta=0 and theta=180")
fig.tight_layout()
print(f"\nfidelity at theta=0 (|0>): {fidelities[0]:.6f}")
print(f"fidelity at theta=90 (|+>): {fidelities[len(fidelities) // 2]:.6f}")
print(f"fidelity at theta=180 (|1>): {fidelities[-1]:.6f}")
print("\nno fixed unitary reaches fidelity 1 across the whole range: exactly the no-cloning theorem's content.")
plt.show()

fidelity at theta=0 (|0>): 1.000000
fidelity at theta=90 (|+>): 0.500023
fidelity at theta=180 (|1>): 1.000000
no fixed unitary reaches fidelity 1 across the whole range: exactly the no-cloning theorem's content.
Total running time of the script: (0 minutes 0.040 seconds)