Two State Systems



In [1]:

%pylab inline




Populating the interactive namespace from numpy and matplotlib



Work in the basis of (non-degenerate) energy eigenstates then $$H = \begin{bmatrix} E_1 & 0 \\ 0 & E_2 \end{bmatrix}$$ with $$E_2 > E_1 \; .$$ Measure time $\tau$ in units of the period $T$ of beats between the energy eigenstates: $$\tau = t / T \quad, \quad T = \frac{h}{E_2 - E_1} \; .$$ A normalized initial state, $$|\psi(0)\rangle = \begin{bmatrix}c_1 e^{i\theta_1} \\ c_2 e^{i\theta_2} \end{bmatrix} \quad, \quad c_1^2 + c_2^2 = 1 \; ,$$ evolves while not being measured as $$|\psi(t)\rangle = e^{i E_1 t/\hbar + i\theta_1} \begin{bmatrix} c_1 \\ c_2 e^{2\pi i \tau + i(\theta_2 - \theta_1)}\end{bmatrix} \; .$$

Consider an arbitrary observable $$Q = \begin{bmatrix} Q_{11} & Q_{12} e^{i\alpha} \\ Q_{12} e^{-i\alpha} & Q_{22} \end{bmatrix}$$ where $Q_{11}, Q_{12}, Q_{22}, \alpha$ are all real. Assume that $Q$ is incompatible with $H$ so that $$[H,Q] = E_1 (r - 1) \begin{bmatrix} 0 & -Q_{12} e^{i\alpha} \\ Q_{12} e^{-i\alpha} & 0 \end{bmatrix} \ne 0 \quad\Rightarrow\quad Q_{12} \ne 0 \; .$$

The corresponding (non-degenerate) eigenvalues are: $$q_\pm = q_0 \pm \Delta q$$ with $$q_0 = \frac{1}{2}\left( Q_{11} + Q_{22}\right) \quad, \quad \Delta q^2 = \left(\frac{Q_{11} - Q_{22}}{2}\right)^2 + Q_{12}^2 \; .$$ The corresponding normalized eigenvectors of $Q$ in the energy eigenbasis are: $$\left|\phi_\pm\right\rangle = \frac{1}{\sqrt{1 + p_\pm^2}} \begin{bmatrix} e^{i\alpha} p_\pm \\ 1 \end{bmatrix}$$ with $$p_\pm = \left( \sqrt{s^2 - 1} \pm s\right) \quad, \quad s \equiv \frac{\Delta q}{Q_{12}} = \sqrt{1 + \left(\frac{Q_{11}-Q_{22}}{2 Q_{12}}\right)^2} \ge 1 \; .$$ The probability of a measurement of $Q$ giving $q_\pm$ after time $t$ is $$\left|\langle \phi_\pm | \psi(t)\rangle\right|^2 = \frac{1}{1+p_\pm^2} \left[ c_2^2 + c_1^2 p_\pm^2 + 2 c_1 c_2 p_\pm \cos\left( 2\pi \tau + \alpha + \theta_2 - \theta_1 \right)\right] \; ,$$ with $$\left|\langle \phi_+ | \psi(t)\rangle\right|^2 + \left|\langle \phi_- | \psi(t)\rangle\right|^2 = c_1^2 + c_2^2 = 1 \; .$$

Note that measurement probabilities for $Q$ are fully specified by $s$ and $\alpha$, and do not depend on $q_0$ or $\Delta q$. Instead, the four degrees of freedom (offset, amplitude, frequency and phase) of the oscillating $\left|\langle \phi_\pm | \psi(t)\rangle\right|^2$ are due to:

• Two of the four degrees of freedom in the Hermitian matrix $Q$.
• One degree of freedom from the state $|\Psi(t)\rangle$ when the measurement is performed.
• One degree of freedom due to the beat frequency $(E_2 - E_1)/h$.

The extra two degrees of freedom in $Q$ determine how the eigenvalues are defined. In particular, two compatible observables $P$ and $Q$ that only differ in a linear transformation between their eigenvalues would have identical measurement probabilities.

Two different observables $A$ and $B$ that do not with $H$, specified by $s_A, s_B$ and $\alpha_A, \alpha_B$ do not commute with each other unless: $$s_A = s_B \quad \text{and} \quad \alpha_A - \alpha_B = n \pi$$ for some integer $n$. If $n$ is even (odd), then $A$ and $B$ have the same (swapped) eigenstates.



In [2]:

def twostate(initial=[1,1], observables=[], measurements=[],
ntrials=4, ncycle=10, nt=100, seed=123):
"""Simulate measurements of arbitrary observables in a two-state universe.

The initial state does not need to be normalized.

Observables are Q0,Q1,Q2,...,QN with [H,Q0] = 0 and [H,Qk] != 0 for k=1,2,...,N.
Q1,...,QN are specified with an array of tuples (s,alpha) where:
- s determines the amplitude of measurement probabilities.
- alpha determines the phase of measurement probabilities.

[Qj,Qk] = 0 only if s[j]=s[k] and alpha[j]-alpha[k] = n pi, with n integer.

Measurements are specified as an array of tuples (t,k) where:
- t specifies when the measurement is performed in units of T, and
- k specifies which observable is measured.
The measurement times must be increasing.
"""
# Normalize and set the initial state.
assert len(initial) == 2
state0 = np.asarray(initial, dtype=complex)
state0 /= np.sqrt(np.sum(np.absolute(initial) ** 2))
# Initialize a time grid covering ncycle periods at the E2-E1 beat frequency
# with nt samples per cycle.
tgrid = np.linspace(0., ncycle, nt * ncycle + 1)
# Initialize probabilties over the time grid.
nobs = len(observables)
prob = np.zeros((nobs + 1, len(tgrid)))
# Calculate eigenstates for each observable.
eigenstate = np.empty((nobs + 1, 2, 2), dtype=complex)
eigenstate[0] = [[1., 0.], [0., 1.]]
if nobs > 0:
s, alpha = zip(*observables)
s = np.array(s)
alpha = np.array(alpha)
p0 = np.sqrt(s ** 2 - 1)
eigenstate[1:, :, 1] = 1.
eigenstate[1:, 0, 0] = np.exp(1j * alpha) * (p0 + s)
eigenstate[1:, 1, 0] = np.exp(1j * alpha) * (p0 - s)
# Normalize.
eigenstate /= np.sqrt(np.sum(np.absolute(eigenstate) ** 2, axis=-1)
).reshape((nobs + 1, 2, 1))
# Initialize labels.
label = [chr(65 + i) for i in range(nobs + 1)]
ymin = '$' + ','.join([f'{chr(97 + i)}_1' for i in range(nobs + 1)]) + '$'
ymax = '$' + ','.join([f'{chr(97 + i)}_2' for i in range(nobs + 1)]) + '$'
# Determine the measurement times.
tmeasure = np.array([when for (when,what) in measurements])
if len(tmeasure) > 0:
assert np.all(np.diff(tmeasure) > 0) and tmeasure[-1] < tgrid[-1]
# Initialize the simulation and plots.
gen = np.random.RandomState(seed=seed)
fig, ax = plt.subplots(ntrials, 1, sharex=True, figsize=(12, 3 * ntrials))
# Loop over realizations.
for k in range(ntrials):
# Loop over measurements.
tnow = 0.
state = state0
for j, tnext in enumerate(np.append(tmeasure, tgrid[-1])):
sel = (tgrid >= tnow) & (tgrid <= tnext)
dt = tgrid - tnow
c1, c2 = np.absolute(state)
theta1, theta2 = np.angle(state)
# Calculate probabilities while system is unobserved during [tnow, tnext].
prob[0, sel] = c1 ** 2
for i in range(nobs):
pp = p0[i] + s[i]
phi = alpha[i] + theta2 - theta1
prob[i + 1, sel] = (
c2 ** 2 + (c1 * pp) ** 2 +
2 * c1 * c2 * pp * np.cos(2 * np.pi * dt[sel] + phi)
) / (1 + pp ** 2)
if j < len(measurements):
# Perform a measurement.
what = measurements[j][1]
if gen.uniform() < prob[what, sel][-1]:
# Project to the measured state.
state = eigenstate[what][0]
else:
state = eigenstate[what][1]
tnow = tnext

ls=['-', '--', ':']
for i in range(nobs + 1):
ax[k].plot(tgrid, prob[i], lw=2, ls=ls[i % len(ls)], label=label[i])
ax[k].legend(ncol=nobs+1)
ax[k].set_xlim(0, tgrid[-1])
ax[k].set_ylim(-0.01, 1.01)
ax[k].set_ylabel(f'Prob to measure {ymax}')
rhs = ax[k].twinx()
rhs.set_ylim(-0.02, 1.02)
rhs.set_yticks([0,1])
rhs.set_yticklabels([ymin, ymax])
ax[-1].set_xlabel('Elapsed time $t$ / $T$')




In [3]:

twostate(initial=[1.5, 1],
observables=[(1.1, -0.5), (1.5, 1.5)],
measurements=[(2.7, 0), (4.2, 1), (6.8, 2), (9.2, 0)],
seed=10)
plt.savefig('twostate_evolution.pdf')