bertiqwerty / exmex

Math parser and evaluator in Rust, capable of partial differentiation, allows the use of custom operators.
Apache License 2.0
39 stars 6 forks source link

Substitution of variables with expressions #42

Closed terrorfisch closed 1 year ago

terrorfisch commented 1 year ago

It would be nice to be able to substitute variables with arbitrary expressions.

My current workaround is to unparse, use regex replacement functionality and re-parse the expression.

bertiqwerty commented 1 year ago

This is similar to #39. Can you give an example how you would want that to work syntactically as library user?

terrorfisch commented 1 year ago

Let's the following method is added to FlatEx

/// EDITED: calls f with all variable names of self in the same order as self.var_names()
fn substituted<F>(&self, f: F) -> Self where F: FnMut(&str) -> Option<Self> {
    todo!()
}
let some_expr = FlatEx::from_str("x*3+y/z")?;

// some other place in code
let substitutions: HashSet = [("x", FlatEx::from_str("a+b")?), ("z", FlatEx::from_str("3.4")?)].into_iter().collect();

let new_expression = some_expr.substituted(|name| subtitutions.get(name));
assert_eq!("(a+b)*3+y/3.4", new_expression.unparse()?)
bertiqwerty commented 1 year ago

Are you missing to loop over the HashSet? Why does substituted have a callable as parameter instead of substituted(&self, name: &str, expr: Self) -> Self?

terrorfisch commented 1 year ago

I added a docstring to clarify the behaviour. I wanted to choose the form that imposes the least in the user. You can use it with a correctly ordered list of substitutions or with an aribtrary map.

One key property is that the substitutions are done at the same time.

let expr = "x/y".parse()?;
let substituted = expr.substituted(|name| {
    match name {
        "x" => Some("y".parse().unwrap()),
        "y" => Some("x".parse().unwrap())
});
assert_eq!("y/x", substituted.unparse())

So in principle I want a rust equivalent to sympy's subs

Alternatively maybe something like:

fn subs<R: IntoIterator<Item=(&str, FlatEx)>>(&self, replacements: R)  -> Result<Self> {
    todo!()
}
bertiqwerty commented 1 year ago

Ah. Yeah. That looks interesting. I will think about how to implement this.

bertiqwerty commented 1 year ago

Like so? https://github.com/bertiqwerty/exmex/blob/7933e1a394884b22d11ff08a85248495c2516a3c/src/expression/deep.rs#L1147