.. 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_field_quantization_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_field_quantization_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_field_quantization_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_field_quantization_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-97 .. 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. .. GENERATED FROM PYTHON SOURCE LINES 98-103 Check ----- [a, a^dagger] = 1 below the truncation; a|n> = sqrt(n)|n-1>, a^dagger|n> = sqrt(n+1)|n+1>; N = a^dagger a has spectrum 0, 1, 2, ...; and <0| a a^dagger |0> = 1 is the vacuum fluctuation behind spontaneous emission. .. GENERATED FROM PYTHON SOURCE LINES 103-108 .. code-block:: Python assert np.max(np.abs(comm[:-1, :-1] - np.eye(n_max - 1))) < 1e-12 assert (lowered_idx, raised_idx) == (n_test - 1, n_test + 1) assert abs(lowered_amp - np.sqrt(n_test)) < 1e-12 and abs(raised_amp - np.sqrt(n_test + 1)) < 1e-12 np.testing.assert_allclose(eigenvalues, np.arange(n_max), atol=1e-12) assert abs(n_expectation_vacuum) < 1e-12 and abs(a_adag_expectation - 1) < 1e-12 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.094 seconds) .. _sphx_glr_download_api_gallery_optics_quantum_optics_plot_field_quantization_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_field_quantization_ladder_operators.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_field_quantization_ladder_operators.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_field_quantization_ladder_operators.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_