pub fn calc_jacobian_with_caching(&mut self) {
use std::collections::HashMap;
let mut derivative_cache: HashMap<(String, String), Expr> = HashMap::new();
let new_jac: Vec<Vec<Expr>> = self.vector_of_functions
.par_iter()
.enumerate()
.map(|(i, function)| {
let mut row = Vec::new();
for j in 0..self.vector_of_variables.len() {
let variable = &self.variable_string[j];
if self.variables_for_all_disrete[i].contains(variable) {
let cache_key = (function.to_string(), variable.clone());
let partial = derivative_cache.get(&cache_key)
.cloned()
.unwrap_or_else(|| {
let mut p = Expr::diff(function, variable);
p = p.symplify();
p
});
row.push(partial);
} else {
row.push(Expr::Const(0.0));
}
}
row
})
.collect();
}
pub fn calc_jacobian_with_indices(&mut self) {
let var_to_index: HashMap<&String, usize> = self.variable_string
.iter()
.enumerate()
.map(|(i, var)| (var, i))
.collect();
let variable_indices: Vec<Vec<usize>> = self.variables_for_all_disrete
.iter()
.map(|vars| {
vars.iter()
.filter_map(|var| var_to_index.get(var).copied())
.collect()
})
.collect();
let new_jac: Vec<Vec<Expr>> = self.vector_of_functions
.par_iter()
.enumerate()
.map(|(i, function)| {
let mut row = vec![Expr::Const(0.0); self.vector_of_variables.len()];
for &j in &variable_indices[i] {
let mut partial = Expr::diff(function, &self.variable_string[j]);
partial = partial.symplify();
row[j] = partial;
}
row
})
.collect();
}
pub fn calc_jacobian_batch_processing(&mut self) {
let mut equation_groups: HashMap<Vec<String>, Vec<usize>> = HashMap::new();
for (i, vars) in self.variables_for_all_disrete.iter().enumerate() {
let mut sorted_vars = vars.clone();
sorted_vars.sort();
equation_groups.entry(sorted_vars).or_default().push(i);
}
let results: Vec<(usize, Vec<Expr>)> = equation_groups
.par_iter()
.flat_map(|(vars, equations)| {
equations.par_iter().map(|&eq_idx| {
let function = &self.vector_of_functions[eq_idx];
let mut row = vec![Expr::Const(0.0); self.vector_of_variables.len()];
for var in vars {
if let Some(j) = self.variable_string.iter().position(|v| v == var) {
let mut partial = Expr::diff(function, var);
partial = partial.symplify();
row[j] = partial;
}
}
(eq_idx, row)
})
})
.collect();
}
pub struct ExprPool {
zeros: Vec<Expr>,
next_index: usize,
}
impl ExprPool {
pub fn new(capacity: usize) -> Self {
Self {
zeros: vec![Expr::Const(0.0); capacity],
next_index: 0,
}
}
pub fn get_zero(&mut self) -> Expr {
if self.next_index < self.zeros.len() {
let expr = self.zeros[self.next_index].clone();
self.next_index += 1;
expr
} else {
Expr::Const(0.0)
}
}
}