RustedSciThe 0.3.29

Rust framework for symbolic and numerical computing: symbolic calculations, nonlinear systems, IVP and BVP for ODE, optimization, fitting and more
Documentation
// Optimization 1: Expression Caching
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();
}

// Optimization 2: Avoid String Comparisons
pub fn calc_jacobian_with_indices(&mut self) {
    // Pre-compute variable name to index mapping
    let var_to_index: HashMap<&String, usize> = self.variable_string
        .iter()
        .enumerate()
        .map(|(i, var)| (var, i))
        .collect();
    
    // Convert variables_for_all_disrete to indices
    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();
}

// Optimization 3: Batch Processing
pub fn calc_jacobian_batch_processing(&mut self) {
    // Group equations by their variable dependencies
    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);
    }
    
    // Process each group in parallel
    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();
}

// Optimization 4: Memory Pool Pattern
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)
        }
    }
}