From f6364ebcac0d0a88a3cc6812fd2120c97b42cc26 Mon Sep 17 00:00:00 2001 From: bnewbold Date: Fri, 2 Dec 2016 01:40:30 -0800 Subject: basic impl of solving equations --- src/bin/mt-tool.rs | 10 ++++++++++ src/modelica_ast.rs | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/bin/mt-tool.rs b/src/bin/mt-tool.rs index 929990f..8ef2464 100644 --- a/src/bin/mt-tool.rs +++ b/src/bin/mt-tool.rs @@ -57,6 +57,8 @@ fn main() { let mut opts = Options::new(); opts.optflag("h", "help", "print this help menu"); opts.optflag("", "version", "print the version"); + opts.optmulti("", "dep", "dependent variable", "VAR"); + opts.optmulti("", "indep", "dependent variable", "VAR"); let matches = match opts.parse(&args[1..]) { Ok(m) => m, @@ -85,6 +87,14 @@ fn main() { let cmd = matches.free[0].clone(); match cmd.as_str() { "parse" => { parse_modelica_files(matches.free[1..].iter().map(|x| x.to_string()).collect()); }, + "solve_for" => { + if matches.free.len() != 2 { + println!("Expected a path to load"); + exit(-1); + } + let me = modelthing::load_model_entry(Path::new(&matches.free[1])).unwrap(); + println!("{:?}", me.ast.solve_for(matches.opt_strs("indep"), matches.opt_strs("dep"))); + }, "transpile_scheme" => { if matches.free.len() != 2 { println!("Expected a single path to load"); diff --git a/src/modelica_ast.rs b/src/modelica_ast.rs index 2958025..f6d32b8 100644 --- a/src/modelica_ast.rs +++ b/src/modelica_ast.rs @@ -116,12 +116,6 @@ impl ModelicaModel { // TODO: allow passing in Q pub fn solve_for(&self, indep_vars: Vec, dep_vars: Vec) -> Result { let constants = self.get_constant_vars(); - let param_objs = self.components.iter().filter(|v| match v.prefix { - Some(ComponentPrefix::Constant) | Some(ComponentPrefix::Parameter) => false, - _ => true, - }); - let params: Vec = param_objs.map(|c| c.name.clone()).collect(); - let mut all_vars: HashSet = HashSet::new(); for eqn in &self.equations { all_vars.extend(eqn.identifiers()); @@ -138,7 +132,11 @@ impl ModelicaModel { // check that V = Q + P + M if all_vars.len() != (constants.len() + indep_vars.len() + dep_vars.len()) { - return Err("Variable counts don't add up".to_string()); + return Err(format!("Variable counts don't add up (V={} Q={} P={} M={})", + all_vars.len(), + constants.len(), + indep_vars.len(), + dep_vars.len())); } // check that all constants are bound and simple @@ -165,8 +163,32 @@ impl ModelicaModel { println!("Soliving for {:?} in terms of params {:?} and constants {:?}, with {} equations", dep_vars, indep_vars, constants, self.equations.len()); - Ok((*self).clone()) // XXX + let mut unsolved_eqns = self.equations.clone(); + let mut solved: Vec = vec![]; + let mut unsolved_vars = dep_vars.clone(); + while unsolved_eqns.len() > 0 { + let next_i = unsolved_eqns + .iter() + .position(|ref x| intersect_strings(&unsolved_vars, &x.identifiers()).len() == 1); + let eqn = match next_i { + None => { return Err("NaiveImplementation (or poor equation selection?)".to_string()); }, + Some(i) => unsolved_eqns.remove(i), + }; + let ref var = intersect_strings(&unsolved_vars, &eqn.identifiers())[0]; + let eqn = eqn.rebalance_for(var.to_string()).expect("rebalance for success"); + solved.push(eqn); + let var_i = unsolved_vars.iter().position(|ref x| x == &var).unwrap(); + unsolved_vars.remove(var_i); + }; + // TODO: sort output equations by LHS + Ok(ModelicaModel{ + name: self.name.clone(), + components: self.components.clone(), + connections: vec![], + equations: solved, + extends: vec![], + }) } } -- cgit v1.2.3