aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbnewbold <bnewbold@robocracy.org>2016-12-02 01:40:30 -0800
committerbnewbold <bnewbold@robocracy.org>2016-12-02 01:40:30 -0800
commitf6364ebcac0d0a88a3cc6812fd2120c97b42cc26 (patch)
tree7c4ea30f71d39872ce63dffeb7dfa63b934a8205
parent7ccdaf4c4b5c50892c654d9f16875c03214168d4 (diff)
downloadmodelthing-f6364ebcac0d0a88a3cc6812fd2120c97b42cc26.tar.gz
modelthing-f6364ebcac0d0a88a3cc6812fd2120c97b42cc26.zip
basic impl of solving equations
-rw-r--r--src/bin/mt-tool.rs10
-rw-r--r--src/modelica_ast.rs38
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<String>, dep_vars: Vec<String>) -> Result<ModelicaModel,String> {
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<String> = param_objs.map(|c| c.name.clone()).collect();
-
let mut all_vars: HashSet<String> = 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<SimpleEquation> = 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![],
+ })
}
}