1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! # Numerical Calculus of Variations
//!
//! This module provides numerical tools for the calculus of variations.
//! It focuses on evaluating the action of a functional for a given path,
//! which is a fundamental step in solving problems like finding geodesics
//! or optimizing paths in physics and engineering.
use crateQuadratureMethod;
use cratequadrature;
use cratedifferentiate;
use cratesubstitute;
use crateExpr;
/// Evaluates the action of a functional for a given path.
///
/// The functional is `S[y] = integral from a to b of L(t, y, y_dot) dt`.
/// This function numerically computes this integral by first substituting the `path`
/// and its derivative into the `lagrangian`, and then performing numerical quadrature.
///
/// # Arguments
/// * `lagrangian` - The Lagrangian expression `L`. It should be an expression in terms of
/// `t_var`, `path_var`, and `path_dot_var`.
/// * `path` - The actual path `y(t)` as an expression.
/// * `t_var` - The name of the independent variable (e.g., "t").
/// * `path_var` - The name of the path variable used in the Lagrangian (e.g., "y").
/// * `path_dot_var` - The name of the path's derivative used in the Lagrangian (e.g., "`y_dot`").
/// * `t_range` - The interval of integration `(a, b)`.
///
/// # Returns
/// A `Result` containing the numerical value of the action integral.
///
/// # Example
/// ```rust
/// use rssn::numerical::calculus_of_variations::evaluate_action;
/// use rssn::symbolic::core::Expr;
///
/// // L = 1/2 * (y_dot)^2 (Free particle action)
/// let t = Expr::new_variable("t");
///
/// let y = Expr::new_variable("y");
///
/// let y_dot = Expr::new_variable("y_dot");
///
/// let lagrangian = Expr::new_mul(
/// Expr::new_constant(0.5),
/// Expr::new_pow(y_dot.clone(), Expr::new_constant(2.0)),
/// );
///
/// // Path: y(t) = t
/// let path = t.clone();
///
/// let action = evaluate_action(&lagrangian, &path, "t", "y", "y_dot", (0.0, 1.0)).unwrap();
///
/// // Integral of 0.5 from 0 to 1 is 0.5
/// assert!((action - 0.5).abs() < 1e-5);
/// ```
///
/// # Errors
///
/// Returns an error if the numerical quadrature fails.
/// Computes the Euler-Lagrange expression for a given Lagrangian.
///
/// The Euler-Lagrange equation is: `d/dt(dL/dy_dot) - dL/dy = 0`.
/// This function returns the symbolic expression `d/dt(dL/dy_dot) - dL/dy`.
///
/// # Arguments
/// * `lagrangian` - The Lagrangian expression `L(t, y, y_dot)`.
/// * `t_var` - The independent variable (e.g., "t").
/// * `path_var` - The path variable (e.g., "y").
/// * `path_dot_var` - The derivative of the path variable (e.g., "`y_dot`").
///
/// # Example
/// ```rust
/// use rssn::numerical::calculus_of_variations::euler_lagrange;
/// use rssn::symbolic::core::Expr;
///
/// // L = 1/2 * m * y_dot^2 - m * g * y
/// // EL: m * y_ddot + m * g = 0
/// ```