SOCR ≫ | TCIU Website ≫ | TCIU GitHub ≫ |
Let’s explore the connections between mathematical and physical interconnections between several fundamental concepts in theoretical physics: the action principle, functional derivatives, group generators, distribution actions, analytic continuation, and energy conservation laws.
The action \(S\) is defined as the time integral of the Lagrangian \(L\) over the path of a system from an initial time \(t_1\) to a final time \(t_2\)
\[S[q] = \int_{t_1}^{t_2} L(q(t), \dot{q}(t), t) \, dt ,\]
where \(q(t)\) represents generalized coordinates and \(\dot{q}(t)\) represents their time derivatives.
For a classical mechanical system with \(n\) degrees of freedom, the Lagrangian is
\[L(q_1, \ldots, q_n, \dot{q}_1, \ldots, \dot{q}_n, t) = T(\dot{q}_1, \ldots, \dot{q}_n) - V(q_1, \ldots, q_n, t)\]
where \(T\) is the kinetic energy and \(V\) is the potential energy of the system.
Hamilton’s principle states that the actual path taken by a physical system between two fixed configurations is the one that makes the action stationary (typically a minimum), i.e., \(\delta S[q] = 0\), where \(\delta\) denotes a variation of the path while keeping the endpoints fixed.
The condition \(\delta S = 0\) leads to the Euler-Lagrange equations, i.e., the equations of motion for the system
\[\frac{\partial L}{\partial q_i} - \frac{d}{dt}\left(\frac{\partial L}{\partial \dot{q}_i}\right) = 0, \quad i = 1, \ldots, n .\]
For a particle of mass \(m\) moving in a potential \(V(\vec{r})\), with \(\vec{r} = (x, y, z)\), the Lagrangian is
\[L = \frac{1}{2}m(\dot{x}^2 + \dot{y}^2 + \dot{z}^2) - V(x, y, z) .\]
Applying the Euler-Lagrange equations yields Newton’s second law \(m\ddot{\vec{r}} = -\vec{\nabla}V(\vec{r})\).
The functional derivative \(\frac{\delta S}{\delta q(t)}\) generalizes the concept of partial derivatives to functionals and measures how the action changes when the path \(q(t)\) is perturbed by an infinitesimal amount \(\delta q(t)\). GIven a functional \(F[q] = \int_{t_1}^{t_2} f(q(t), \dot{q}(t), t) \, dt\), the functional derivative is
\[\frac{\delta F}{\delta q(t)} = \frac{\partial f}{\partial q} - \frac{d}{dt}\left(\frac{\partial f}{\partial \dot{q}}\right)\]
The Euler-Lagrange equations can be rewritten in terms of functional derivatives
\[\frac{\delta S}{\delta q_i(t)} = 0, \quad i = 1, \ldots, n ,\]
which is a compact form emphasizing that the physical path is one where the action is stationary with respect to all possible variations.
The functional derivative of the action is related to the generalized force \(Q_i\) acting on the system \(Q_i = \frac{\delta S}{\delta q_i(t)}\). When the system follows the physical path, these generalized forces vanish, indicating equilibrium in the variational sense.
Noether’s theorem establishes that each continuous symmetry of the action corresponds to a conservation law. For time-translation symmetry, the conserved quantity is energy. When the Lagrangian does not explicitly depend on time (\(\frac{\partial L}{\partial t} = 0\)), the energy (Hamiltonian) \(H\) is conserved, i.e.,
\[H = \sum_{i=1}^{n} \dot{q}_i \frac{\partial L}{\partial \dot{q}_i} - L = \text{constant} .\]
The Hamiltonian is obtained from the Lagrangian via a Legendre transformation
\[H(q, p, t) = \sum_{i=1}^{n} p_i \dot{q}_i - L(q, \dot{q}, t) ,\]
where the generalized momenta are \(p_i = \frac{\partial L}{\partial \dot{q}_i}\).
From the Hamiltonian, we can derive Hamilton’s canonical equations
\[\dot{q}_i = \frac{\partial H}{\partial p_i}, \quad \dot{p}_i = -\frac{\partial H}{\partial q_i},\] which represent an alternative formulation to the Euler-Lagrange equations.
For systems with time-translation symmetry, the Hamiltonian generates time evolution via
\[\frac{d}{dt}f(q, p, t) = \{f, H\} + \frac{\partial f}{\partial t},\]
where \(\{f, H\}\) is the Poisson bracket,
\[\{f, H\} = \sum_{i=1}^{n} \left(\frac{\partial f}{\partial q_i}\frac{\partial H}{\partial p_i} - \frac{\partial f}{\partial p_i}\frac{\partial H}{\partial q_i}\right) .\]
A Lie group \(G\) is a continuous group that is also a differentiable manifold where the tangent space at the identity element forms a Lie algebra \(\mathfrak{g}\). For a one-parameter subgroup \(g(t) \in G\), the generator \(X \in \mathfrak{g}\) is
\[X = \left.\frac{d}{dt}g(t)\right|_{t=0} .\]
Generators of symmetry transformations correspond to conserved quantities in physical systems, e.g,.
Symbolically, if \(U(g)\) is a unitary representation of a Lie group element \(g\), and \(X\) is the corresponding generator, then \(U(g) = e^{iXt}\). In classical mechanics, generators form a Lie algebra under the Poisson bracket, i.e., the components of angular momentum satisfy
\[\{L_i, L_j\} = \sum_{k=1}^{3} \epsilon_{ijk} L_k ,\]
where \(\epsilon_{ijk}\) is the Levi-Civita symbol. In quantum mechanics, the Poisson bracket corresponds to the commutator
\[[L_i, L_j] = i\hbar \sum_{k=1}^{3} \epsilon_{ijk} L_k .\] In essence, the Poisson bracket is the realization of the classical limit of the quantum commutator
\[\lim_{\hbar \to 0} \frac{1}{i\hbar}[\hat{A}, \hat{B}] = \{A, B\} .\]
{} [Noether’s theorem in terms of generators] Let \(G\) be a generator of a symmetry transformation that leaves the action invariant, then \(G\) is a conserved quantity \(\frac{dG}{dt} = 0\).
In quantum mechanics, the transition amplitude between states is given by Feynman’s path integral
\[\langle q_f, t_f | q_i, t_i \rangle = \int \mathcal{D}q \, e^{\frac{i}{\hbar}S[q]},\]
where \(\mathcal{D}q\) represents integration over all possible paths connecting \((q_i, t_i)\) to \((q_f, t_f)\). The probability amplitude \(e^{\frac{i}{\hbar}S[q]}\) assigns a complex weight to each path, with the classical path corresponding to the stationary phase.
More rigorously, the path integral is defined as a limit
\[\int \mathcal{D}q \, e^{\frac{i}{\hbar}S[q]} = \lim_{N \to \infty} \left(\frac{m}{2\pi i \hbar \epsilon}\right)^{N/2} \int \prod_{j=1}^{N-1} dq_j \, \exp\left[\frac{i}{\hbar}\sum_{j=0}^{N-1} \epsilon L\left(\frac{q_{j+1}-q_j}{\epsilon}, \frac{q_{j+1}+q_j}{2}\right)\right] ,\]
where \(\epsilon = \frac{t_f - t_i}{N}\) and \(q_0 = q_i\), \(q_N = q_f\).
{} [Distribution Action] The distribution action extends the concept of action to encompass statistical distributions over paths. In statistical field theory, a partition function is
\[Z = \int \mathcal{D}\phi \, e^{-S_E[\phi]},\]
where \(S_E\) is the Euclidean action obtained via analytic continuation.
The distribution action treats the action as a functional that assigns probabilities (or probability amplitudes) to different field configurations.
Analytic continuation extends a function from a subset of its domain to a larger domain, preserving its analytic properties. A function \(f(z)\) is analytic at a point \(z_0\) if it is differentiable in a neighborhood of \(z_0\). When a pair of analytic functions \(f(z)\) and \(g(z)\) agree on a set with an accumulation point, then \(f(z) = g(z)\) throughout their domains of analyticity.
The Wick rotation is a specific analytic continuation from real time \(t\) (event order) to purely imaginary time \(\tau = it\). Under this transformation, the Minkowski metric becomes Euclidean
\[ds^2 = -dt^2 + d\vec{x}^2 \to d\tau^2 + d\vec{x}^2 .\]
The (general) action transforms as \(S = \int dt \, L \to iS_E = i\int d\tau \, L_E\), where \(S_E\) is the Euclidean action and the path integral becomes
\[\int \mathcal{D}\phi \, e^{\frac{i}{\hbar}S[\phi]} \to \int \mathcal{D}\phi \, e^{-\frac{1}{\hbar}S_E[\phi]} .\]
This transforms oscillatory integrals into exponentially decaying integrals that are more amenable to numerical and analytical techniques.
Under eriodic boundary conditions \(\phi(\tau) = \phi(\tau + \beta)\), the analytic continuation \(t \to i\tau\) connects quantum field theory to thermal field theory, where \(\beta = \frac{1}{k_B T}\). The partition function of a quantum system at temperature \(T\) is
\[Z = \text{Tr}(e^{-\beta \hat{H}}) = \int \mathcal{D}\phi \, e^{-S_E[\phi]},\] where the functional integration is performed over fields satisfying periodic boundary conditions in imaginary time.
Analytic continuation is useful for deriving dispersion relations that connect the real and imaginary parts of response functions through the Kramers-Kronig relations
\[\text{Re}\chi(\omega) = \frac{1}{\pi}\mathcal{P}\int_{-\infty}^{\infty} \frac{\text{Im}\chi(\omega')}{\omega' - \omega} d\omega' ,\]
\[\text{Im}\chi(\omega) = -\frac{1}{\pi}\mathcal{P}\int_{-\infty}^{\infty} \frac{\text{Re}\chi(\omega')}{\omega' - \omega} d\omega' ,\]
where \(\mathcal{P}\) denotes the principal value. These relations follow from the analyticity of response functions in the upper half of the complex plane, which is a consequence of causality.
The action principle provides as a unifying framework for classical and quantum physics
The action of the kime phase distribution \(\Phi_t\) on kime-test functions \(\psi\) is defined by \[\langle \Phi_t, \psi \rangle = \int_{-\pi}^{\pi} \psi(t e^{i\theta}) p_\Phi(\theta) \, d\theta .\] This distribution action on test-functions generalizes measurable quantities by focusing on their functional properties rather than individual values of \(\theta\). This analytic representation emphasizes the role of smoothing and averaging over phase, which parallels the experimental approach of repeated draws of a random variable. The former is more abstract but better suited to describe underlying kime properties, where as the latter is more useful for data-driven estimation, prediction and dynamical quantification.
The extension from global to local symmetries introduces gauge fields and leads to gauge theories. For a field theory with global symmetry under a transformation \(\phi \to \phi + \delta\phi\), requiring local invariance under \(\phi \to \phi + \delta\phi(x)\) necessitates introducing a gauge field \(A_\mu(x)\) with transformation properties that compensate for the local nature of the symmetry.
The gauge-invariant action takes the form \[S = \int d^4x \left[\mathcal{L}_{\text{matter}}(\phi, D_\mu\phi) - \frac{1}{4}F_{\mu\nu}F^{\mu\nu}\right] ,\]
where \(D_\mu = \partial_\mu - igA_\mu\) is the covariant derivative and \(F_{\mu\nu} = \partial_\mu A_\nu - \partial_\nu A_\mu + ig[A_\mu, A_\nu]\) is the field strength tensor.
{}: The action principle can be formulated in terms of differential geometry
In general relativity, the Einstein-Hilbert action is \(S_{EH} = \frac{1}{16\pi G}\int d^4x \sqrt{-g}R ,\) where \(g\) is the determinant of the metric tensor \(g_{\mu\nu}\) and \(R\) is the Ricci scalar.
The concepts of action, functional derivatives, group generators, distribution actions, analytic continuation, and energy are interconnected and their further integration with complex-time (kime) representation may be valuable. The action principle appears as the central unifying concept to build upon. The interplay between physical principles and mathematical structures, demonstrate how symmetry, geometry, and variational principles come together describe the fundamental laws of nature. The main question is how to connect the statistical and data-science formulation of complex time where the repeated sampling of the controlled processes provides a mechanism to obtain a higher-dimensional representation that facilitates probing the unobservable kime-phase distributions.
In this experiment, we showcase Hamilton’s principle of least action using a simple harmonic oscillator. We explore how different paths connecting the same initial and final points have different values of the action, and how the classical path corresponds to the path of stationary action.
To start we’ll use these basic functions.
library(plotly)
library(purrr)
# Core functions for our simulations
calculate_lagrangian <- function(x, v, m, k) {
# Lagrangian L = T - V = 0.5*m*v^2 - 0.5*k*x^2
L <- 0.5*m*v^2 - 0.5*k*x^2
return(L)
}
calculate_action <- function(x, t, m, k) {
# Calculate velocity using central difference
dt <- t[2] - t[1]
v <- c(diff(x)/dt, (x[length(x)] - x[length(x)-1])/dt)
# Compute Lagrangian at each point
L <- calculate_lagrangian(x, v, m, k)
# Action is integral of L over time
S <- sum(L) * dt
return(S)
}
# Function to generate a path with perturbations
generate_path <- function(t, omega, amplitude = 1, perturbation = NULL,
pert_amplitude = 0, pert_frequency = 1) {
x_classical <- amplitude * cos(omega * t)
if (!is.null(perturbation)) {
x <- x_classical + pert_amplitude * perturbation(pert_frequency * omega * t)
} else {
x <- x_classical
}
return(x)
}
# Function to calculate action for multiple paths
calculate_actions_for_paths <- function(paths_list, t, m, k) {
# Use lapply and unlist instead of map_dbl to avoid dependency on purrr
actions <- unlist(lapply(paths_list, function(path) calculate_action(path, t, m, k)))
return(actions)
}
The first interactive simulation allows how various parameters affect the action and observe the principle of stationary action in practice. The simulation above demonstrates several key aspects of the action principle:
Principle of Stationary Action: The classical path (green) corresponds to the path with the minimum action value among all paths connecting the same endpoints.
Variational Principle: As we move away from the classical path (with increasing perturbation amplitude), the action increases, demonstrating that the classical path makes the action stationary.
Physical Meaning: The color gradient in the perturbation paths visualizes how far each path deviates from optimality in terms of action. Paths closer to the classical one (bluer) have action values closer to the minimum.
# Visualization of a simple harmonic oscillator action
# # Parameters
# m <- 1 # mass
# k <- 1 # spring constant
# omega <- sqrt(k/m) # angular frequency
# T <- 2*pi/omega # period
#
# # Generate data for different paths
# t <- seq(0, T, length.out=100)
# x_classical <- cos(omega*t) # classical path
# x_perturbed1 <- cos(omega*t) + 0.2*sin(2*omega*t) # perturbed path 1
# x_perturbed2 <- cos(omega*t) + 0.4*sin(3*omega*t) # perturbed path 2
#
# # Calculate actions
# calculate_action <- function(x, t) {
# # Approximate velocities
# v <- c(diff(x)/diff(t), 0)
#
# # Lagrangian L = T - V = 0.5*m*v^2 - 0.5*k*x^2
# L <- 0.5*m*v^2 - 0.5*k*x^2
#
# # Action is integral of L over time
# S <- sum(L) * (t[2] - t[1])
# return(S)
# }
#
# actions <- c(
# calculate_action(x_classical, t),
# calculate_action(x_perturbed1, t),
# calculate_action(x_perturbed2, t)
# )
#
# # Create data frame for plotting
# df <- data.frame(
# time = rep(t, 3),
# position = c(x_classical, x_perturbed1, x_perturbed2),
# path = rep(c("Classical", "Perturbed 1", "Perturbed 2"), each=length(t))
# )
#
# # Create plot
# ggplot(df, aes(x=time, y=position, color=path)) +
# geom_line() +
# labs(title="Different Paths of a Harmonic Oscillator",
# subtitle=paste("Classical path has stationary action S =", round(actions[1], 2)),
# x="Time", y="Position") +
# theme_minimal()
# Simulation parameters - user adjustable
m <- 1.0 # mass
k <- 2.0 # spring constant
omega <- sqrt(k/m) # angular frequency
T <- 2*pi/omega # period
num_points <- 200 # resolution of our simulation
num_paths <- 10 # number of perturbed paths to generate
# Time points for simulation
t <- seq(0, T, length.out = num_points)
# Generate classical path
x_classical <- generate_path(t, omega)
# Generate perturbed paths with varying amplitudes
perturbation_amplitudes <- seq(0.05, 0.5, length.out = num_paths)
paths_list <- list()
paths_list[[1]] <- x_classical # First path is classical
for (i in 1:num_paths) {
# Add sine perturbation with varying amplitude and frequency
paths_list[[i+1]] <- generate_path(
t, omega,
perturbation = sin,
pert_amplitude = perturbation_amplitudes[i],
pert_frequency = 2
)
}
# Calculate action for each path
path_names <- c("Classical", paste("Perturbed", 1:num_paths))
actions <- calculate_actions_for_paths(paths_list, t, m, k)
# Create data frame for plotting trajectories
trajectory_df <- map_dfr(1:(num_paths+1), function(i) {
data.frame(
time = t,
position = paths_list[[i]],
path = path_names[i],
action = actions[i]
)
})
# Create the trajectory plot
trajectory_plot <- plot_ly(height = 500) %>%
add_trace(data = trajectory_df %>% filter(path == "Classical"),
x = ~time, y = ~position, type = 'scatter', mode = 'lines',
name = 'Classical Path',
line = list(color = 'green', width = 3)) %>%
layout(title = "Different Paths of a Harmonic Oscillator",
xaxis = list(title = "Time"),
yaxis = list(title = "Position"),
hovermode = "closest")
# Add perturbed paths with color gradient based on action value
perturbed_only <- trajectory_df %>% filter(path != "Classical")
action_range <- range(perturbed_only$action)
norm_actions <- (perturbed_only$action - action_range[1]) / (action_range[2] - action_range[1])
for (i in 1:num_paths) {
path_data <- perturbed_only %>% filter(path == paste("Perturbed", i))
# Color from blue (close to classical) to red (far from classical)
color_val <- rgb(norm_actions[i*num_points], 0, 1-norm_actions[i*num_points])
trajectory_plot <- trajectory_plot %>%
add_trace(data = path_data, x = ~time, y = ~position,
type = 'scatter', mode = 'lines',
name = paste0(path_data$path[1], " (S = ", round(path_data$action[1], 2), ")"),
line = list(color = color_val, width = 1.5))
}
# Plot the action values for each path
action_df <- data.frame(
path = factor(path_names, levels = path_names),
action = actions
)
action_plot <- plot_ly(data = action_df, x = ~path, y = ~action, type = 'bar',
marker = list(color = c('green', colorRampPalette(c('blue', 'red'))(num_paths)))) %>%
layout(title = "Action Value for Each Path",
xaxis = list(title = "Path"),
yaxis = list(title = "Action Value"),
showlegend = FALSE)
# Display the plots
subplot(trajectory_plot, action_plot, nrows = 2, heights = c(0.7, 0.3)) %>%
layout(title = "Principle of Stationary Action Demonstration",
annotations = list(
list(
x = 0.5,
y = 1.05,
text = "The classical path minimizes the action functional",
showarrow = FALSE,
xref = "paper",
yref = "paper"
)
))
This experiment shows Noether’s theorem, connecting symmetries to conservation laws and shows how time-translation symmetry leads to energy conservation, and how spatial symmetries relate to momentum conservation.
# Function to simulate a physical system with symmetries
simulate_system_with_symmetries <- function(t, initial_conditions,
params = list(m = 1, k = 1, g = 9.8),
system_type = "harmonic") {
# Unpack initial conditions
x0 <- initial_conditions$x0
v0 <- initial_conditions$v0
# Unpack parameters
m <- params$m
k <- params$k
g <- params$g
# Define different system types
if (system_type == "harmonic") {
# Harmonic oscillator (time-translation symmetry)
x <- x0 * cos(sqrt(k/m) * t) + v0/sqrt(k/m) * sin(sqrt(k/m) * t)
v <- -x0 * sqrt(k/m) * sin(sqrt(k/m) * t) + v0 * cos(sqrt(k/m) * t)
# Potential and kinetic energy
V <- 0.5 * k * x^2
T <- 0.5 * m * v^2
# Total energy (should be conserved due to time symmetry)
E <- T + V
return(data.frame(t = t, x = x, v = v, T = T, V = V, E = E))
} else if (system_type == "free_particle") {
# Free particle (spatial translation symmetry)
x <- x0 + v0 * t
v <- rep(v0, length(t))
# Momentum (should be conserved due to spatial symmetry)
p <- m * v
# Kinetic energy
T <- 0.5 * m * v^2
return(data.frame(t = t, x = x, v = v, p = p, T = T))
} else if (system_type == "gravity") {
# Particle in gravity (broken time symmetry)
x <- x0 + v0 * t - 0.5 * g * t^2
v <- v0 - g * t
# Potential and kinetic energy
V <- m * g * x
T <- 0.5 * m * v^2
# Total energy (not conserved due to time-dependent potential)
E <- T + V
return(data.frame(t = t, x = x, v = v, T = T, V = V, E = E))
}
}
# Time points for simulation
t <- seq(0, 10, length.out = 200)
# Initial conditions
initial_conditions <- list(x0 = 1, v0 = 0)
# Simulate three different systems
harmonic_data <- simulate_system_with_symmetries(t, initial_conditions,
params = list(m = 1, k = 2),
system_type = "harmonic")
free_particle_data <- simulate_system_with_symmetries(t, initial_conditions,
params = list(m = 1),
system_type = "free_particle")
gravity_data <- simulate_system_with_symmetries(t, initial_conditions,
params = list(m = 1, g = 0.5),
system_type = "gravity")
# Interactive plots for each system
harmonic_plot <- plot_ly(harmonic_data, height = 400) %>%
add_trace(x = ~t, y = ~E, type = 'scatter', mode = 'lines', name = 'Total Energy',
line = list(color = 'red', width = 3)) %>%
add_trace(x = ~t, y = ~T, type = 'scatter', mode = 'lines', name = 'Kinetic Energy',
line = list(color = 'blue')) %>%
add_trace(x = ~t, y = ~V, type = 'scatter', mode = 'lines', name = 'Potential Energy',
line = list(color = 'green')) %>%
layout(title = "Harmonic Oscillator (Time-Translation Symmetry)",
xaxis = list(title = "Time"),
yaxis = list(title = "Energy"),
annotations = list(
list(
x = 5,
y = max(harmonic_data$E) * 1.1,
text = "Energy is conserved due to time-translation symmetry",
showarrow = FALSE
)
))
free_particle_plot <- plot_ly(free_particle_data, height = 400) %>%
add_trace(x = ~t, y = ~p, type = 'scatter', mode = 'lines', name = 'Momentum',
line = list(color = 'purple', width = 3)) %>%
add_trace(x = ~t, y = ~T, type = 'scatter', mode = 'lines', name = 'Kinetic Energy',
line = list(color = 'blue')) %>%
layout(title = "Free Particle (Spatial-Translation Symmetry)",
xaxis = list(title = "Time"),
yaxis = list(title = "Momentum/Energy"),
annotations = list(
list(
x = 5,
y = max(free_particle_data$p) * 1.1,
text = "Momentum is conserved due to spatial-translation symmetry",
showarrow = FALSE
)
))
gravity_plot <- plot_ly(gravity_data, height = 400) %>%
add_trace(x = ~t, y = ~E, type = 'scatter', mode = 'lines', name = 'Total Energy',
line = list(color = 'red', width = 3)) %>%
add_trace(x = ~t, y = ~T, type = 'scatter', mode = 'lines', name = 'Kinetic Energy',
line = list(color = 'blue')) %>%
add_trace(x = ~t, y = ~V, type = 'scatter', mode = 'lines', name = 'Potential Energy',
line = list(color = 'green')) %>%
layout(title = "Particle in Gravity (Broken Time-Translation Symmetry)",
xaxis = list(title = "Time"),
yaxis = list(title = "Energy"),
annotations = list(
list(
x = 5,
y = min(gravity_data$E) * 0.9,
text = "Energy is not conserved due to broken time-translation symmetry",
showarrow = FALSE
)
))
# Display the plots
subplot(harmonic_plot, free_particle_plot, gravity_plot, nrows = 3) %>%
layout(title = "Noether's Theorem: Symmetries and Conservation Laws")
This experiment visualizes the quantum path integral approach by simulating quantum tunneling through a potential barrier and shows the classical path as just one contribution to the quantum amplitude, and how multiple paths contribute to quantum phenomena.
The path integral formulation of quantum mechanics shows:
# Function to calculate potential
calculate_potential <- function(x, barrier_height = 1, barrier_width = 1) {
# Double well potential with barrier
potential <- numeric(length(x))
for (i in 1:length(x)) {
if (abs(x[i]) < barrier_width/2) {
potential[i] <- barrier_height
} else {
potential[i] <- 0.1 * (x[i]^2 - barrier_width^2)^2
}
}
return(potential)
}
# Function to generate random paths for path integral
generate_random_paths <- function(x_start, x_end, n_steps, n_paths, max_deviation = 0.5) {
paths <- matrix(0, nrow = n_paths, ncol = n_steps)
# Linear path from start to end
straight_path <- seq(x_start, x_end, length.out = n_steps)
for (i in 1:n_paths) {
# Start with straight path
current_path <- straight_path
# Add random deviations, keeping endpoints fixed
deviations <- c(0, rnorm(n_steps-2, 0, max_deviation), 0)
paths[i,] <- current_path + deviations
}
return(paths)
}
# Calculate quantum action (with ħ term)
calculate_quantum_action <- function(path, dt, m = 1, potential_fn, hbar = 1) {
n <- length(path)
dx <- diff(path)
v <- dx/dt
# Kinetic energy
T <- 0.5 * m * v^2
# Potential energy (average of adjacent points)
V <- potential_fn(path[-1]) # potential at midpoints
# Quantum action includes i*ħ
S <- sum((T - V) * dt)
return(S)
}
# Calculate quantum amplitude (complex)
calculate_amplitude <- function(action, hbar = 1) {
return(exp(1i * action / hbar))
}
# Simulate quantum tunneling
simulate_tunneling <- function(x_start = -2, x_end = 2, n_steps = 50, n_paths = 100,
barrier_params = list(height = 1.5, width = 1.5),
hbar = 0.5) {
# Time step
dt <- 0.1
# Generate random paths
paths <- generate_random_paths(x_start, x_end, n_steps, n_paths)
# Create potential function with barrier
potential_fn <- function(x) calculate_potential(x, barrier_params$height, barrier_params$width)
# Position grid for potential plot
x_grid <- seq(-3, 3, length.out = 200)
potential_grid <- potential_fn(x_grid)
# Calculate action and amplitude for each path
results <- data.frame(
path_id = 1:n_paths,
action = numeric(n_paths),
amplitude_real = numeric(n_paths),
amplitude_imag = numeric(n_paths),
amplitude_abs = numeric(n_paths)
)
path_data <- list()
for (i in 1:n_paths) {
# Calculate action for this path
action_val <- calculate_quantum_action(paths[i,], dt, potential_fn = potential_fn, hbar = hbar)
amplitude <- calculate_amplitude(action_val, hbar)
results$action[i] <- action_val
results$amplitude_real[i] <- Re(amplitude)
results$amplitude_imag[i] <- Im(amplitude)
results$amplitude_abs[i] <- Mod(amplitude)
# Store path data for plotting
path_data[[i]] <- data.frame(
x = paths[i,],
t = seq(0, (n_steps-1)*dt, by = dt),
path_id = i,
action = action_val,
amplitude_abs = Mod(amplitude)
)
}
# Combine path data
all_paths <- do.call(rbind, path_data)
# Create potential plot
potential_plot <- plot_ly(height = 300) %>%
add_trace(x = x_grid, y = potential_grid, type = 'scatter', mode = 'lines',
name = 'Potential', line = list(color = 'black', width = 2)) %>%
layout(title = "Potential Barrier",
xaxis = list(title = "Position"),
yaxis = list(title = "Potential Energy"))
# Plot a subset of paths colored by amplitude
paths_to_plot <- sample(1:n_paths, min(30, n_paths))
path_plot <- plot_ly(height = 300) %>%
layout(title = "Sample Quantum Paths",
xaxis = list(title = "Time"),
yaxis = list(title = "Position"))
for (i in paths_to_plot) {
path_subset <- all_paths %>% filter(path_id == i)
# Normalize amplitude for color
norm_amplitude <- (path_subset$amplitude_abs[1] - min(results$amplitude_abs)) /
(max(results$amplitude_abs) - min(results$amplitude_abs))
# Color from blue (low amplitude) to red (high amplitude)
color_val <- rgb(norm_amplitude, 0, 1-norm_amplitude)
path_plot <- path_plot %>%
add_trace(data = path_subset, x = ~t, y = ~x, type = 'scatter', mode = 'lines',
line = list(color = color_val),
showlegend = FALSE)
}
# Create amplitude distribution plot
amplitude_plot <- plot_ly(data = results, height = 300) %>%
add_trace(x = ~amplitude_real, y = ~amplitude_imag, type = 'scatter', mode = 'markers',
marker = list(size = 5, color = ~amplitude_abs,
colorscale = 'Viridis', showscale = TRUE)) %>%
layout(title = "Distribution of Path Amplitudes in Complex Plane",
xaxis = list(title = "Re(amplitude)"),
yaxis = list(title = "Im(amplitude)"))
# Return all plots and data
return(list(
potential_plot = potential_plot,
path_plot = path_plot,
amplitude_plot = amplitude_plot,
results = results,
all_paths = all_paths
))
}
# Run the quantum tunneling simulation
tunneling_sim <- simulate_tunneling(hbar = 0.5)
# Display the plots
subplot(tunneling_sim$potential_plot,
tunneling_sim$path_plot,
tunneling_sim$amplitude_plot,
nrows = 3) %>%
layout(title = "Quantum Tunneling via Path Integral Approach",
annotations = list(
list(
x = 0.5,
y = 1.05,
text = paste("Quantum paths contribute with complex amplitudes e^(iS/ħ),",
"allowing tunneling through classically forbidden regions"),
showarrow = FALSE,
xref = "paper",
yref = "paper"
)
))
This experiment demonstrates how analytic continuation transforms oscillatory path integrals into more manageable Euclidean path integrals, facilitating both numerical calculations and connections to statistical mechanics.
# Function to simulate Minkowski and Euclidean path integrals
simulate_analytic_continuation <- function(n_paths = 1000, n_steps = 20, hbar = 1) {
# Time parameters
t_max <- 2
t <- seq(0, t_max, length.out = n_steps)
dt <- t[2] - t[1]
# Generate paths for simple harmonic oscillator
m <- 1
k <- 1
omega <- sqrt(k/m)
# Classical path
x_classical <- cos(omega * t)
# Generate random paths with fixed endpoints
x_start <- x_classical[1]
x_end <- x_classical[n_steps]
paths <- matrix(0, nrow = n_paths, ncol = n_steps)
paths[,1] <- x_start
paths[,n_steps] <- x_end
# Random fluctuations around straight line
for (i in 1:n_paths) {
# Generate random intermediate points
for (j in 2:(n_steps-1)) {
# Linear interpolation plus random deviation
paths[i,j] <- x_start + (j-1)/(n_steps-1) * (x_end - x_start) +
rnorm(1, 0, 0.3 * sqrt(dt))
}
}
# Calculate actions and amplitudes for both Minkowski and Euclidean cases
results <- data.frame(
path_id = 1:n_paths,
minkowski_action = numeric(n_paths),
minkowski_amplitude_re = numeric(n_paths),
minkowski_amplitude_im = numeric(n_paths),
euclidean_action = numeric(n_paths),
euclidean_weight = numeric(n_paths)
)
for (i in 1:n_paths) {
# Current path
path <- paths[i,]
# Calculate velocities
v <- c(diff(path)/dt, 0)
# Lagrangian L = T - V
L <- 0.5 * m * v[1:(n_steps-1)]^2 - 0.5 * k * path[1:(n_steps-1)]^2
# Minkowski action (real time)
S_M <- sum(L * dt)
results$minkowski_action[i] <- S_M
# Minkowski amplitude e^(iS/ħ)
amplitude <- exp(1i * S_M / hbar)
results$minkowski_amplitude_re[i] <- Re(amplitude)
results$minkowski_amplitude_im[i] <- Im(amplitude)
# Euclidean action (imaginary time)
# Mathematically: t → iτ, S → iS_E
# Lagrangian becomes L_E = T + V (sign change)
L_E <- 0.5 * m * v[1:(n_steps-1)]^2 + 0.5 * k * path[1:(n_steps-1)]^2
S_E <- sum(L_E * dt)
results$euclidean_action[i] <- S_E
# Euclidean weight e^(-S_E/ħ)
results$euclidean_weight[i] <- exp(-S_E / hbar)
}
# Normalize Euclidean weights for visualization
results$euclidean_weight_norm <- results$euclidean_weight / max(results$euclidean_weight)
# Prepare path data for plotting
path_data <- list()
selected_paths <- sample(1:n_paths, 30) # Select random paths to plot
for (i in selected_paths) {
path_data[[length(path_data) + 1]] <- data.frame(
t = t,
x = paths[i,],
path_id = i,
minkowski_action = results$minkowski_action[i],
euclidean_weight = results$euclidean_weight[i],
euclidean_weight_norm = results$euclidean_weight_norm[i]
)
}
# Add classical path
path_data[[length(path_data) + 1]] <- data.frame(
t = t,
x = x_classical,
path_id = 0,
minkowski_action = NA,
euclidean_weight = NA,
euclidean_weight_norm = NA
)
all_paths <- bind_rows(path_data)
# Return all the computed data
return(list(
paths = paths,
results = results,
path_data = all_paths,
classical_path = x_classical,
t = t
))
}
# Load required libraries
library(ggplot2)
library(dplyr)
library(tidyr)
library(patchwork)
library(viridis)
library(grid)
library(gridExtra)
# Run the simulation
set.seed(42)
sim_results <- simulate_analytic_continuation(n_paths = 1000, n_steps = 50, hbar = 0.5)
# Plot a selection of paths with color representing Euclidean weight
p1 <- ggplot(filter(sim_results$path_data, path_id != 0)) +
geom_line(aes(x = t, y = x, group = path_id, color = euclidean_weight_norm), alpha = 0.7) +
geom_line(data = filter(sim_results$path_data, path_id == 0),
aes(x = t, y = x), color = "red", size = 1, linetype = "dashed") +
scale_color_viridis_c(name = "Euclidean\nWeight", direction = -1) +
labs(title = "Quantum Paths for Harmonic Oscillator",
subtitle = "Colored by Euclidean weight (higher = darker)",
x = "Time",
y = "Position") +
theme_minimal() +
theme(legend.position = "right")
# Distribution of Minkowski actions and amplitudes
p2 <- ggplot(sim_results$results) +
geom_point(aes(x = minkowski_amplitude_re, y = minkowski_amplitude_im, color = minkowski_action),
alpha = 0.5) +
scale_color_viridis_c(name = "Minkowski\nAction") +
coord_fixed() +
labs(title = "Minkowski Path Integral",
subtitle = "Complex amplitude distribution",
x = "Re(e^(iS/ħ))",
y = "Im(e^(iS/ħ))") +
theme_minimal() +
theme(legend.position = "right")
# Distribution of Euclidean actions and weights
p3 <- ggplot(sim_results$results) +
geom_histogram(aes(x = euclidean_action, weight = euclidean_weight), bins = 30, fill = "steelblue") +
labs(title = "Euclidean Path Integral",
subtitle = "Action distribution weighted by e^(-S/ħ)",
x = "Euclidean Action",
y = "Weighted Frequency") +
theme_minimal()
# Relationship between Minkowski and Euclidean actions
p4 <- ggplot(sim_results$results) +
geom_point(aes(x = euclidean_action, y = minkowski_action, color = euclidean_weight_norm),
alpha = 0.5) +
scale_color_viridis_c(name = "Euclidean\nWeight", direction = -1) +
labs(title = "Relationship Between Actions",
subtitle = "Minkowski vs. Euclidean",
x = "Euclidean Action",
y = "Minkowski Action") +
theme_minimal() +
theme(legend.position = "right")
# Combine plots
combined_plot <- (p1 + p2) / (p3 + p4) +
plot_layout(guides = "collect") &
theme(legend.position = "right")
print(combined_plot)