Skip to content

Commit

Permalink
Full Infix Notation Fix and Multiplication Tree Depth Bugfix (#872)
Browse files Browse the repository at this point in the history
## Summary of Changes
- Fixes an issue where when a binary multiplication tree got too deep,
we failed to fully flatten it, leading to Petrinet parsing errors.
- Fixes an error with infix expressions, so should make it so if a
transition has division in it, the infix expression will properly show
that as well, instead of `*` like it was showing before.

### Related issues

Resolves #868 #871 #403

---------

Co-authored-by: Justin <[email protected]>
  • Loading branch information
Free-Quarks and Justin authored Mar 27, 2024
1 parent e437b49 commit 3c957fe
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 89 deletions.
120 changes: 42 additions & 78 deletions skema/skema-rs/mathml/src/acset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,18 @@ impl From<Vec<MathExpressionTree>> for GeneralizedAMR {
parameter_vec.push(parameter.clone());
}

// now to trim the numbers from the parameters field
let mut nums = Vec::<usize>::new();
for (k, param) in parameter_vec.iter().enumerate() {
if param.id.parse::<f32>().is_ok() {
nums.push(k);
}
}

for num in nums.iter().rev() {
parameter_vec.remove(num.clone());
}

let header = Header {
name: "Model".to_string(),
schema: "G-AMR".to_string(),
Expand Down Expand Up @@ -746,7 +758,7 @@ impl From<Vec<FirstOrderODE>> for PetriNet {
// first is we need to replace any terms with more than 2 exp_states with subterms, these are simply
// terms that need to be distributed (ASSUMPTION, MOST A TRANSTION CAN HAVE IS 2 IN AND 2 OUT)
// but first we need to inherit the dynamic state to each sub term
let mut composite_term_ind = Vec::<usize>::new();
/*let mut composite_term_ind = Vec::<usize>::new();
let mut sub_terms = Vec::<PnTerm>::new();
for (j, t) in terms.clone().iter().enumerate() {
if t.exp_states.len() > 2 && t.sub_terms.is_some() {
Expand All @@ -763,7 +775,7 @@ impl From<Vec<FirstOrderODE>> for PetriNet {
terms.remove(*i);
}
// replace with subterms
terms.append(&mut sub_terms);
terms.append(&mut sub_terms);*/

// now for polarity pairs of terms we need to construct the transistions
let mut paired_term_indices = Vec::<usize>::new();
Expand Down Expand Up @@ -845,25 +857,9 @@ impl From<Vec<FirstOrderODE>> for PetriNet {
};
transitions_vec.insert(transitions.clone());

let mut expression_string = "".to_string();

for param in t.0.parameters.clone().iter() {
expression_string = format!("{}{}*", expression_string.clone(), param.clone());
}

let exp_len = t.0.exp_states.len();
for (i, exp) in t.0.exp_states.clone().iter().enumerate() {
if i != exp_len - 1 {
expression_string =
format!("{}{}*", expression_string.clone(), exp.clone());
} else {
expression_string = format!("{}{}", expression_string.clone(), exp.clone());
}
}

let rate = Rate {
target: transitions.id.clone(),
expression: expression_string.clone(), // the second term needs to be the product of the inputs
expression: t.0.expression_infix.clone()[1..t.0.expression_infix.clone().len()-1].to_string(),// the second
expression_mathml: Some(t.0.expression.clone()),
};
rate_vec.push(rate.clone());
Expand All @@ -886,25 +882,9 @@ impl From<Vec<FirstOrderODE>> for PetriNet {
};
transitions_vec.insert(transitions.clone());

let mut expression_string = "".to_string();

for param in t.0.parameters.clone().iter() {
expression_string = format!("{}{}*", expression_string.clone(), param.clone());
}

let exp_len = t.0.exp_states.len() - 1;
for (i, exp) in t.0.exp_states.clone().iter().enumerate() {
if i != exp_len {
expression_string =
format!("{}{}*", expression_string.clone(), exp.clone());
} else {
expression_string = format!("{}{}", expression_string.clone(), exp.clone());
}
}

let rate = Rate {
target: transitions.id.clone(),
expression: expression_string.clone(), // the second term needs to be the product of the inputs
expression: t.0.expression_infix.clone()[1..t.0.expression_infix.clone().len()-1].to_string(),// the second
expression_mathml: Some(t.0.expression.clone()),
};
rate_vec.push(rate.clone());
Expand Down Expand Up @@ -942,29 +922,9 @@ impl From<Vec<FirstOrderODE>> for PetriNet {
};
transitions_vec.insert(transitions.clone());

let mut expression_string = "".to_string();

if !term.exp_states.is_empty() {
let exp_len = term.exp_states.len() - 1;
for (i, exp) in term.exp_states.clone().iter().enumerate() {
if i != exp_len {
expression_string =
format!("{}{}*", expression_string.clone(), exp.clone());
} else {
expression_string =
format!("{}{}", expression_string.clone(), exp.clone());
}
}
}

for param in term.parameters.clone().iter() {
expression_string =
format!("{}{}", expression_string.clone(), param.clone());
}

let rate = Rate {
target: transitions.id.clone(),
expression: expression_string.clone(), // the second term needs to be the product of the inputs
expression: term.expression_infix.clone()[1..term.expression_infix.clone().len()-1].to_string(),// the second term needs to be the product of the inputs
expression_mathml: Some(term.expression.clone()),
};
rate_vec.push(rate.clone());
Expand All @@ -983,29 +943,9 @@ impl From<Vec<FirstOrderODE>> for PetriNet {
};
transitions_vec.insert(transitions.clone());

let mut expression_string = "".to_string();

if !term.exp_states.is_empty() {
let exp_len = term.exp_states.len() - 1;
for (i, exp) in term.exp_states.clone().iter().enumerate() {
if i != exp_len {
expression_string =
format!("{}{}*", expression_string.clone(), exp.clone());
} else {
expression_string =
format!("{}{}", expression_string.clone(), exp.clone());
}
}
}

for param in term.parameters.clone().iter() {
expression_string =
format!("{}{}", expression_string.clone(), param.clone());
}

let rate = Rate {
target: transitions.id.clone(),
expression: expression_string.clone(), // the second term needs to be the product of the inputs
expression: term.expression_infix.clone()[1..term.expression_infix.clone().len()-1].to_string(),// the second
expression_mathml: Some(term.expression.clone()),
};
rate_vec.push(rate.clone());
Expand All @@ -1018,6 +958,18 @@ impl From<Vec<FirstOrderODE>> for PetriNet {
parameter_vec.sort();
parameter_vec.dedup();

// now to trim the numbers from the parameters field
let mut nums = Vec::<usize>::new();
for (k, param) in parameter_vec.iter().enumerate() {
if param.id.parse::<f32>().is_ok() {
nums.push(k);
}
}

for num in nums.iter().rev() {
parameter_vec.remove(num.clone());
}

// construct the PetriNet
let ode = Ode {
rates: Some(rate_vec),
Expand Down Expand Up @@ -1271,6 +1223,18 @@ impl From<Vec<FirstOrderODE>> for RegNet {
parameter_vec.sort();
parameter_vec.dedup();

// now to trim the numbers from the parameters field
let mut nums = Vec::<usize>::new();
for (k, param) in parameter_vec.iter().enumerate() {
if param.id.parse::<f32>().is_ok() {
nums.push(k);
}
}

for num in nums.iter().rev() {
parameter_vec.remove(num.clone());
}

// ------------------------------------------

let model = ModelRegNet {
Expand Down
57 changes: 46 additions & 11 deletions skema/skema-rs/mathml/src/parsers/first_order_ode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ pub struct PnTerm {
pub exp_states: Vec<String>, // list of state variables in term
pub polarity: bool, // polarity of term
pub expression: String, // content mathml for the expression
pub expression_infix: String,
pub parameters: Vec<String>, // list of parameters in term
pub sub_terms: Option<Vec<PnTerm>>, // This is to handle when we need to distribute or not for terms.
pub math_vec: Option<MathExpressionTree>, // This is to allows for easy distribution using our current frame work
Expand Down Expand Up @@ -263,6 +264,7 @@ pub fn get_terms(sys_states: Vec<String>, ode: FirstOrderODE) -> Vec<PnTerm> {
exp_states: [x.to_string().clone()].to_vec(),
polarity: true,
expression: "".to_string(),
expression_infix: "".to_string(),
parameters: Vec::<String>::new(),
sub_terms: None,
math_vec: None,
Expand All @@ -274,6 +276,7 @@ pub fn get_terms(sys_states: Vec<String>, ode: FirstOrderODE) -> Vec<PnTerm> {
exp_states: Vec::<String>::new(),
polarity: true,
expression: "".to_string(),
expression_infix: "".to_string(),
parameters: [x.to_string().clone()].to_vec(),
sub_terms: None,
math_vec: None,
Expand Down Expand Up @@ -380,7 +383,8 @@ pub fn get_term_power(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> P
dyn_state: "temp".to_string(),
exp_states,
polarity,
expression: MathExpressionTree::Cons(Multiply, eq).to_cmml(),
expression: MathExpressionTree::Cons(Multiply, eq.clone()).to_cmml(),
expression_infix: MathExpressionTree::Cons(Multiply, eq).to_infix_expression(),
parameters: variables,
sub_terms: None,
math_vec: None,
Expand Down Expand Up @@ -442,6 +446,7 @@ pub fn get_terms_add(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> Ve
exp_states: [x.to_string().clone()].to_vec(),
polarity: true,
expression: MathExpressionTree::Cons(Add, [arg.clone()].to_vec()).to_cmml(),
expression_infix: MathExpressionTree::Cons(Add, [arg.clone()].to_vec()).to_infix_expression(),
parameters: Vec::<String>::new(),
sub_terms: None,
math_vec: Some(arg.clone()),
Expand All @@ -453,6 +458,7 @@ pub fn get_terms_add(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> Ve
exp_states: Vec::<String>::new(),
polarity: true,
expression: MathExpressionTree::Cons(Add, [arg.clone()].to_vec()).to_cmml(),
expression_infix: MathExpressionTree::Cons(Add, [arg.clone()].to_vec()).to_infix_expression(),
parameters: [x.to_string().clone()].to_vec(),
sub_terms: None,
math_vec: Some(arg.clone()),
Expand Down Expand Up @@ -568,6 +574,7 @@ pub fn get_terms_sub(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> Ve
polarity: false,
expression: MathExpressionTree::Cons(Subtract, [eq[0].clone()].to_vec())
.to_cmml(),
expression_infix: MathExpressionTree::Cons(Subtract, [eq[0].clone()].to_vec()).to_infix_expression(),
parameters: Vec::<String>::new(),
sub_terms: None,
math_vec: Some(eq[0].clone()),
Expand All @@ -580,6 +587,7 @@ pub fn get_terms_sub(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> Ve
polarity: false,
expression: MathExpressionTree::Cons(Subtract, [eq[0].clone()].to_vec())
.to_cmml(),
expression_infix: MathExpressionTree::Cons(Subtract, [eq[0].clone()].to_vec()).to_infix_expression(),
parameters: [x1.to_string()].to_vec(),
sub_terms: None,
math_vec: Some(eq[0].clone()),
Expand Down Expand Up @@ -705,10 +713,12 @@ pub fn get_terms_sub(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> Ve
let mut polarity = true;
let mut expression =
MathExpressionTree::Cons(Add, [arg.clone()].to_vec()).to_cmml();
let mut expression_infix = MathExpressionTree::Cons(Add, [arg.clone()].to_vec()).to_infix_expression();
if i == 1 {
polarity = false;
expression =
MathExpressionTree::Cons(Subtract, [arg.clone()].to_vec()).to_cmml()
MathExpressionTree::Cons(Subtract, [arg.clone()].to_vec()).to_cmml();
expression_infix = MathExpressionTree::Cons(Subtract, [arg.clone()].to_vec()).to_infix_expression()
}
for state in sys_states.iter() {
if x.to_string() == *state {
Expand All @@ -721,6 +731,7 @@ pub fn get_terms_sub(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> Ve
exp_states: [x.to_string().clone()].to_vec(),
polarity,
expression,
expression_infix,
parameters: Vec::<String>::new(),
sub_terms: None,
math_vec: Some(arg.clone()),
Expand All @@ -732,6 +743,7 @@ pub fn get_terms_sub(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> Ve
exp_states: Vec::<String>::new(),
polarity,
expression,
expression_infix,
parameters: [x.to_string().clone()].to_vec(),
sub_terms: None,
math_vec: Some(arg.clone()),
Expand Down Expand Up @@ -836,7 +848,8 @@ pub fn get_term_div(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> PnT
dyn_state: "temp".to_string(),
exp_states,
polarity,
expression: MathExpressionTree::Cons(Multiply, eq).to_cmml(),
expression: MathExpressionTree::Cons(Multiply, eq.clone()).to_cmml(),
expression_infix: MathExpressionTree::Cons(Multiply, eq).to_infix_expression(),
parameters: variables,
sub_terms: None,
math_vec: None,
Expand Down Expand Up @@ -936,6 +949,7 @@ pub fn get_terms_mult(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> P
exp_states: [x.to_string().clone()].to_vec(),
polarity: true,
expression: "temp".to_string(),
expression_infix: "temp".to_string(),
parameters: Vec::<String>::new(),
sub_terms: None,
math_vec: Some(arg.clone()),
Expand All @@ -947,6 +961,7 @@ pub fn get_terms_mult(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> P
exp_states: Vec::<String>::new(),
polarity: true,
expression: "temp".to_string(),
expression_infix: "temp".to_string(),
parameters: [x.to_string().clone()].to_vec(),
sub_terms: None,
math_vec: Some(arg.clone()),
Expand Down Expand Up @@ -1022,7 +1037,8 @@ pub fn get_terms_mult(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> P
dyn_state: "temp".to_string(),
exp_states,
polarity,
expression: MathExpressionTree::Cons(Multiply, eq).to_cmml(),
expression: MathExpressionTree::Cons(Multiply, eq.clone()).to_cmml(),
expression_infix: MathExpressionTree::Cons(Multiply, eq).to_infix_expression(),
parameters: variables,
sub_terms: Some(terms),
math_vec: None,
Expand Down Expand Up @@ -1121,7 +1137,8 @@ pub fn get_term_mult(sys_states: Vec<String>, eq: Vec<MathExpressionTree>) -> Pn
dyn_state: "temp".to_string(),
exp_states,
polarity,
expression: MathExpressionTree::Cons(Multiply, eq).to_cmml(),
expression: MathExpressionTree::Cons(Multiply, eq.clone()).to_cmml(),
expression_infix: MathExpressionTree::Cons(Multiply, eq).to_infix_expression(),
parameters: variables,
sub_terms: None,
math_vec: None,
Expand All @@ -1135,10 +1152,19 @@ pub fn flatten_mults(mut equation: MathExpressionTree) -> MathExpressionTree {
match y[1].clone() {
Cons(x1, y1) => match x1 {
Multiply => {
let temp1 = flatten_mults(y1[0].clone());
let temp2 = flatten_mults(y1[1].clone());
let mut temp1 = flatten_mults(y1[0].clone());
let mut temp2 = flatten_mults(y1[1].clone());
y.remove(1);
y.append(&mut [temp1, temp2].to_vec())
if let Cons(Multiply, ref mut y2) = temp1 {
y.append(&mut y2.clone());
} else {
y.append(&mut [temp1].to_vec());
}
if let Cons(Multiply, ref mut y2) = temp2 {
y.append(&mut y2.clone());
} else {
y.append(&mut [temp2].to_vec());
}
}
_ => {
let temp1 = y[1].clone();
Expand All @@ -1151,10 +1177,19 @@ pub fn flatten_mults(mut equation: MathExpressionTree) -> MathExpressionTree {
match y[0].clone() {
Cons(x0, y0) => match x0 {
Multiply => {
let temp1 = flatten_mults(y0[0].clone());
let temp2 = flatten_mults(y0[1].clone());
let mut temp1 = flatten_mults(y0[0].clone());
let mut temp2 = flatten_mults(y0[1].clone());
y.remove(0);
y.append(&mut [temp1, temp2].to_vec());
if let Cons(Multiply, ref mut y2) = temp1 {
y.append(&mut y2.clone());
} else {
y.append(&mut [temp1].to_vec());
}
if let Cons(Multiply, ref mut y2) = temp2 {
y.append(&mut y2.clone());
} else {
y.append(&mut [temp2].to_vec());
}
}
_ => {
let temp1 = y[0].clone();
Expand Down
Loading

0 comments on commit 3c957fe

Please sign in to comment.