.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/optics/quantum_optics/plot_ladder_operators.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_optics_quantum_optics_plot_ladder_operators.py: Dirac's quantization of the electromagnetic field: ladder operators ========================================================================== Dirac gave the first fully quantum treatment of radiation by promoting each field mode to a quantum harmonic oscillator, with non-commuting annihilation and creation operators :math:`\hat a,\hat a^\dagger` satisfying :math:`[\hat a,\hat a^\dagger]=1`. Photon number becomes the oscillator's excitation number, :math:`\hat n=\hat a^\dagger\hat a`, with :math:`\hat a` and :math:`\hat a^\dagger` respectively removing and adding one field quantum -- exactly the ladder structure Einstein's 1905 light quanta had implied but never derived. This example builds :math:`\hat a` and :math:`\hat a^\dagger` directly with :func:`~physicskit.quantum.core.operators.annihilation_operator` and :func:`~physicskit.quantum.core.operators.creation_operator`, verifies the commutation relation and the ladder action on Fock states, and shows the vacuum-fluctuation fact behind Dirac's other major result: even the vacuum :math:`\lvert0\rangle` is not "nothing" to :math:`\hat a^\dagger`, which is exactly what makes spontaneous emission unavoidable. .. GENERATED FROM PYTHON SOURCE LINES 23-33 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from physicskit.quantum.core.operators import ( annihilation_operator, commutator, creation_operator, number_operator, ) .. GENERATED FROM PYTHON SOURCE LINES 34-36 Building the ladder operators, and checking the commutator ------------------------------------------------------------------ .. GENERATED FROM PYTHON SOURCE LINES 36-46 .. code-block:: Python n_max = 12 a = annihilation_operator(n_max) a_dag = creation_operator(n_max) comm = commutator(a, a_dag) print("[a, a_dagger] on the truncated basis (should be the identity, except at the truncation edge):") print(np.round(comm.real, 4)) print(f"\nmax deviation from identity, excluding the last (truncated) basis state: {np.max(np.abs(comm[:-1, :-1] - np.eye(n_max - 1))):.2e}") print(f"deviation at the truncated edge (n_max-1): {comm[-1, -1].real:.4f} (a finite-basis artifact -- a true infinite Fock space has none)") .. rst-class:: sphx-glr-script-out .. code-block:: none [a, a_dagger] on the truncated basis (should be the identity, except at the truncation edge): [[ 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] [ 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] [ 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0.] [ 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.] [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.] [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0.] [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. -11.]] max deviation from identity, excluding the last (truncated) basis state: 1.78e-15 deviation at the truncated edge (n_max-1): -11.0000 (a finite-basis artifact -- a true infinite Fock space has none) .. GENERATED FROM PYTHON SOURCE LINES 47-51 The ladder action on Fock states -------------------------------------- a|n> = sqrt(n)|n-1>, a_dagger|n> = sqrt(n+1)|n+1> -- verified directly as matrix-vector products against basis vectors, not assumed. .. GENERATED FROM PYTHON SOURCE LINES 51-63 .. code-block:: Python n_test = 4 psi_n = np.zeros(n_max, dtype=complex) psi_n[n_test] = 1.0 lowered = a @ psi_n raised = a_dag @ psi_n lowered_idx, lowered_amp = np.argmax(np.abs(lowered)), np.abs(lowered).max() raised_idx, raised_amp = np.argmax(np.abs(raised)), np.abs(raised).max() print(f"\nstarting from |n={n_test}>:") print(f" a|n> has its only nonzero entry at index {lowered_idx}, amplitude {lowered_amp:.6f} (expected sqrt({n_test})={np.sqrt(n_test):.6f})") print(f" a_dagger|n> has its only nonzero entry at index {raised_idx}, amplitude {raised_amp:.6f} (expected sqrt({n_test + 1})={np.sqrt(n_test + 1):.6f})") .. rst-class:: sphx-glr-script-out .. code-block:: none starting from |n=4>: a|n> has its only nonzero entry at index 3, amplitude 2.000000 (expected sqrt(4)=2.000000) a_dagger|n> has its only nonzero entry at index 5, amplitude 2.236068 (expected sqrt(5)=2.236068) .. GENERATED FROM PYTHON SOURCE LINES 64-66 The number operator's ladder-derived spectrum ---------------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 66-78 .. code-block:: Python N = number_operator(n_max) eigenvalues = np.sort(np.linalg.eigvalsh(N).real) print(f"\nnumber operator N=a_dagger*a eigenvalues: {np.round(eigenvalues, 6)}") print("(exactly 0, 1, 2, ..., n_max-1 -- built entirely from the ladder operators above)") fig, ax = plt.subplots(figsize=(6, 4.5)) ax.plot(eigenvalues, "o-", color="steelblue") ax.set_xlabel("eigenstate index") ax.set_ylabel("photon number eigenvalue") ax.set_title(r"Spectrum of $\hat N=\hat a^\dagger\hat a$: the discrete ladder") fig.tight_layout() .. image-sg:: /api/gallery/optics/quantum_optics/images/sphx_glr_plot_ladder_operators_001.png :alt: Spectrum of $\hat N=\hat a^\dagger\hat a$: the discrete ladder :srcset: /api/gallery/optics/quantum_optics/images/sphx_glr_plot_ladder_operators_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none number operator N=a_dagger*a eigenvalues: [ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.] (exactly 0, 1, 2, ..., n_max-1 -- built entirely from the ladder operators above) .. GENERATED FROM PYTHON SOURCE LINES 79-86 The vacuum is not "nothing" to a_dagger: the seed of spontaneous emission ------------------------------------------------------------------------------------ <0|a a_dagger|0> = 1, even though <0|a_dagger a|0> = 0 (the vacuum has no photons to remove). This asymmetry -- a direct consequence of [a, a_dagger]=1 -- is exactly what Dirac showed drives spontaneous emission: an excited atom, coupled to the quantized field, is never coupled to "nothing" even when the field starts in vacuum. .. GENERATED FROM PYTHON SOURCE LINES 86-96 .. code-block:: Python vacuum = np.zeros(n_max, dtype=complex) vacuum[0] = 1.0 n_expectation_vacuum = np.real(vacuum.conj() @ N @ vacuum) a_adag_expectation = np.real(vacuum.conj() @ (a @ a_dag) @ vacuum) print(f"\n<0|N|0> = {n_expectation_vacuum:.6f} (no photons present)") print(f"<0| a a_dagger |0> = {a_adag_expectation:.6f} (nonzero! the vacuum still 'kicks back' on a_dagger)") print("this single nonzero vacuum matrix element is the seed of spontaneous emission Dirac derived") print("from first principles, rather than inserting Einstein's 1917 'A coefficient' by hand.") plt.show() .. rst-class:: sphx-glr-script-out .. code-block:: none <0|N|0> = 0.000000 (no photons present) <0| a a_dagger |0> = 1.000000 (nonzero! the vacuum still 'kicks back' on a_dagger) this single nonzero vacuum matrix element is the seed of spontaneous emission Dirac derived from first principles, rather than inserting Einstein's 1917 'A coefficient' by hand. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.031 seconds) .. _sphx_glr_download_api_gallery_optics_quantum_optics_plot_ladder_operators.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_ladder_operators.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_ladder_operators.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_ladder_operators.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_