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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//! symbolic engine features:
//! 1) turns a String expression into a symbolic expression
//! 2) turns a symbolic expression into a Rust function
//! 3) turns a symbolic expression into a string expression for printing and control results
//! 4) anaytical differentiation and comparsion with numerical differentiation
//! 5) analytical function of many variables
//! 6) calculating Jacobians (symbolic expressions and Rust functions) for various ODE problems
//! 7) analytical Taylor expansion
//! 8) analytical integration
//! 9) numerical integration
//! 10) vectors and matrices of symbolic expressions
//! 11) multiple symbolic operations (substitution, addition, multiplication, etc.)
/// a module turns a String expression into a symbolic expression
///# Example
/// ```
/// use RustedSciThe::symbolic::symbolic_functions::Jacobian;
/// use RustedSciThe::symbolic::symbolic_engine::Expr;
///let input = "x^2.3* log(x+y+y^2.6)"; //log(x)/y-x^2.3 log(x+y+y^2.6)-exp(x-y)/(x+y)
/// let parsed_expression = Expr::parse_expression(input);
///println!(" parsed_expression {}", parsed_expression);
/// let parsed_function = parsed_expression.lambdify_borrowed_thread_safe( &["x","y"]);
/// println!("{}, Rust function: {} \n",input, parsed_function(&[1.0, 2.0]));
/// ```
/// Symbolic engine 1) turns a String expression into a symbolic expression
/// 2) turns a symbolic expression into a Rust function
/// 3) turns a symbolic expression into a string expression for printing and control results
///
/// # Example#
/// ```
///
/// use RustedSciThe::symbolic::parse_expr;
/// use RustedSciThe::symbolic::symbolic_engine::Expr;
///let input = "x^2.3* log(x+y+y^2.6)"; //log(x)/y-x^2.3 log(x+y+y^2.6)-exp(x-y)/(x+y)
/// let parsed_expression = Expr::parse_expression(input);
///println!(" parsed_expression {}", parsed_expression);
/// let parsed_function = parsed_expression.sym_to_str("x");
/// println!("{}, Rust function: {} \n",input, parsed_function);
///
/// ```
/// Example2#
/// ```
///
/// use RustedSciThe::symbolic::parse_expr;
/// use RustedSciThe::symbolic::symbolic_engine::Expr;
/// let input = "exp(x)+log(y)"; //log(x)/y-x^2.3 *log(x+y+y^2.6)-exp(x-y)/(x+y) + (log((x-y)/(x+y)))^2
/// // here you've got symbolic expression
/// let parsed_expression = Expr::parse_expression(input);
/// println!(" parsed_expression {}", parsed_expression);
/// // turn symbolic expression to a pretty human-readable string
/// let parsed_function = parsed_expression.sym_to_str("x");
/// println!("{}, sym to string: {} \n",input, parsed_function);
/// // return vec of all arguments
/// let all = parsed_expression.all_arguments_are_variables();
/// println!("all arguments are variables {:?}",all);
/// let variables = parsed_expression.extract_variables();
/// println!("variables {:?}",variables);
/// // differentiate with respect to x and y
/// let df_dx = parsed_expression.diff("x");
/// let df_dy = parsed_expression.diff("y");
/// println!("df_dx = {}, df_dy = {}", df_dx, df_dy);
/// //convert symbolic expression to a Rust function and evaluate the function
/// let args = vec!["x","y"];
/// let function_of_x_and_y = parsed_expression.lambdify_borrowed_thread_safe( args.as_slice() );
/// let f_res = function_of_x_and_y( &[1.0, 2.0] );
/// println!("f_res = {}", f_res);
/// // or you dont want to pass arguments you can use lambdify_wrapped, arguments will be found inside function
/// let function_of_x_and_y = parsed_expression.lambdify_wrapped( );
/// let f_res = function_of_x_and_y( (&[1.0, 2.0]).to_vec() );
/// println!("f_res2 = {}", f_res);
/// let start = vec![ 1.0, 1.0];
/// let end = vec![ 2.0, 2.0];
/// // evaluate function of 2 or more arguments using linspace for defining vectors of arguments
/// let result = parsed_expression.lamdified_from_linspace(start.clone(), end.clone(), 10);
/// println!("evaluated function of 2 arguments = {:?}", result);
/// // find vector of derivatives with respect to all arguments
/// let vector_of_derivatives = parsed_expression.diff_multi();
/// println!("vector_of_derivatives = {:?}, {}", vector_of_derivatives, vector_of_derivatives.len());
/// // compare numerical and analtical derivatives for a given linspace defined by start, end values and number of values.
/// // max_norm - maximum norm of the difference between numerical and analtical derivatives
/// let comparsion = parsed_expression.compare_num(start, end, 100, 1e-6);
/// println!(" result_of compare = {:?}", comparsion);
/// ```
/// Example3#
/// ```
/// use RustedSciThe::symbolic::symbolic_engine::Expr;
/// use RustedSciThe::symbolic::symbolic_functions::Jacobian;
/// let input = "log(x)";
/// let f = Expr::parse_expression(input);
/// //convert symbolic expression to a Rust function and evaluate the function
/// let f_res = f.lambdify1D()(1.0);
/// let df_dx = f.diff("x");
/// println!("df_dx = {}, log(1) = {}", df_dx, f_res);
/// let input = "x+exp(x)";
/// let f = Expr::parse_expression(input);
/// let f_res = f.lambdify1D()(1.0);
/// println!("f_res = {}", f_res);
/// let start = 0.0;
/// let end = 10 as f64;
/// let num_values = 100;
/// let max_norm = 1e-6;
/// // compare numerical and analtical derivatives for a given linspace defined by start, end values and number of values.
/// // a norm of the difference between the two of them is returned, and the answer is true if the norm is below max_norm
/// let (norm, res) = f.compare_num1D("x", start, end, num_values, max_norm);
/// println!("norm = {}, res = {}", norm, res);
/// ```
/// basic functionality for analytical differentiation of symbolic expressions
///
/// calculate symbolic jacobian and evaluate it
/// Example#
/// ```
/// use RustedSciThe::symbolic::symbolic_functions::Jacobian;
/// let mut Jacobian_instance = Jacobian::new();
/// // function of 2 or more arguments
/// let vec_of_expressions = vec![ "2*x^3+y".to_string(), "1".to_string()];
/// // set vector of functions
/// Jacobian_instance.set_funcvecor_from_str(vec_of_expressions);
/// // set vector of variables
/// Jacobian_instance.set_varvecor_from_str("x, y");
/// // calculate symbolic jacobian
/// Jacobian_instance.calc_jacobian();
/// // transform into human...kind of readable form
/// Jacobian_instance.readable_jacobian();
/// // generate jacobian made of regular rust functions
/// Jacobian_instance.jacobian_generate(vec!["x", "y"]);
/// println!("Jacobian_instance: functions {:?}. Variables {:?}", Jacobian_instance.vector_of_functions, Jacobian_instance.vector_of_variables);
/// println!("Jacobian_instance: Jacobian {:?} readable {:?}.", Jacobian_instance.symbolic_jacobian, Jacobian_instance.readable_jacobian);
/// for i in 0.. Jacobian_instance.symbolic_jacobian.len() {
/// for j in 0.. Jacobian_instance.symbolic_jacobian[i].len() {
/// println!("Jacobian_instance: Jacobian {} row {} colomn {:?}", i, j, Jacobian_instance.symbolic_jacobian[i][j]);
/// }
/// }
/// // calculate element of jacobian (just for control)
/// let ij_element = Jacobian_instance.calc_ij_element(0, 0, vec!["x", "y"],vec![10.0, 2.0]) ;
/// println!("ij_element = {:?} \n", ij_element);
/// // evaluate jacobian to numerical values
/// Jacobian_instance. lambdify_and_ealuate_funcvector(vec!["x", "y"], vec![10.0, 2.0]);
/// println!("function vector = {:?} \n", Jacobian_instance.evaluated_functions);
/// // lambdify and evaluate function vector to numerical values
/// Jacobian_instance. lambdify_and_ealuate_funcvector(vec!["x", "y"], vec![10.0, 2.0]);
/// println!("function vector = {:?} \n", Jacobian_instance.evaluated_functions);
/// // or first lambdify
/// Jacobian_instance.lambdify_funcvector(vec!["x", "y"]);
/// // then evaluate
/// Jacobian_instance.evaluate_funvector_lambdified(vec![10.0, 2.0]);
/// println!("function vector after evaluate_funvector_lambdified = {:?} \n", Jacobian_instance.evaluated_functions);
/// // evaluate jacobian to nalgebra matrix format
/// Jacobian_instance.evaluate_func_jacobian_DMatrix(vec![10.0, 2.0]);
/// println!("Jacobian_DMatrix = {:?} \n", Jacobian_instance.evaluated_jacobian_DMatrix);
/// Jacobian_instance.evaluate_funvector_lambdified_DVector(vec![10.0, 2.0]);
/// println!("function vector after evaluate_funvector_lambdified_DMatrix = {:?} \n", Jacobian_instance.evaluated_functions_DVector);
/// ```
/// creating residual functions and Jacobian for BVP
/// modern shared IVP backend contracts and params-aware symbolic preparation
/// thin IVP bridge into the generic AOT lifecycle
/// high-level generated-backend orchestration for IVP symbolic problems
/// basic functionality for symbolic integration (only elementary functions)
/// also numerical integration of symbolic functions
pub
pub
/// matrices and vectors of symbolic expressions
///______________________________________________________________________________________________________________________________________________
/// the collection of utility functions mainly for bracket parsing and proceeding
/// _____________________________________________________________________________________________________________________________________________