use of gov.sandia.n2a.language.OperatorBinary in project n2a by frothga.
the class Variable method flattenExpressions.
public void flattenExpressions(Variable v) {
if (assignment != v.assignment && !(// This line and the next say that * and / are compatible with each other, so ignore that case.
(assignment == MULTIPLY && v.assignment == DIVIDE) || (assignment == DIVIDE && v.assignment == MULTIPLY))) {
Backend.err.get().println("WARNING: Flattened variable " + v.container.prefix() + "." + v.nameString() + " has different combining operator than target (" + container.prefix() + "." + nameString() + "). Resolving in favor of higher-precedence operator.");
v.assignment = assignment = Math.max(v.assignment, assignment);
}
if (v.assignment == REPLACE) {
// We want equations from the lower level to override any pre-existing equations in the upper level.
// Why? Because the lower-level equations represent an elaboration of the model, and are thus more specific.
// Note that Internal executes contained populations after the upper-level equations, so the contained
// populations take precedence even without flattening.
NavigableSet<EquationEntry> equations0 = equations;
equations = new TreeSet<EquationEntry>();
// First add the lower-level equations, so they take precedence.
for (EquationEntry e2 : v.equations) add(e2);
for (EquationEntry e0 : equations0) add(e0);
} else {
// For combiners, it is necessary to create new equations for every combination of conditions.
// Of course, unconditional equations and equations with matching conditions can be combined more directly.
// First step is to augment both equation sets with an unconditional form, if they lack it.
EquationEntry query = new EquationEntry(this, "");
EquationEntry e = find(query);
// expression and condition are null; we deal with this below
if (e == null)
add(query);
query = new EquationEntry(v, "");
e = v.find(query);
if (e == null)
v.add(query);
NavigableSet<EquationEntry> equations0 = equations;
equations = new TreeSet<EquationEntry>();
for (EquationEntry e0 : equations0) {
for (EquationEntry e1 : v.equations) {
if (// Condition strings are exactly the same. TODO: compare ASTs for actual logic equivalence.
e0.compareTo(e1) == 0) {
e = new EquationEntry(this, "");
e.condition = e0.condition;
} else if (e0.condition == null) {
// If so, then only those equations should be merged, so skip this one.
if (find(e1) != null)
continue;
e = new EquationEntry(this, "");
e.condition = e1.condition;
} else if (e1.condition == null) {
// Check if e0.condition exists in v.equations
if (v.find(e0) != null)
continue;
e = new EquationEntry(this, "");
e.condition = e0.condition;
} else {
e = new EquationEntry(this, "");
AND and = new AND();
e.condition = and;
and.operand0 = e0.condition;
and.operand1 = e1.condition;
}
if (e.condition != null)
e.ifString = e.condition.render();
// merge expressions
if (e0.expression == null) {
// which could also be null
e.expression = e1.expression;
} else if (e1.expression == null) {
e.expression = e0.expression;
} else // Both expressions exist
{
OperatorBinary op = null;
Function f = null;
switch(v.assignment) {
case ADD:
op = new Add();
break;
case MULTIPLY:
op = new Multiply();
break;
case DIVIDE:
op = new Divide();
break;
case MIN:
f = new Min();
break;
case MAX:
f = new Max();
break;
}
if (op != null) {
op.operand0 = e0.expression;
op.operand1 = e1.expression;
e.expression = op;
} else if (f != null) {
f.operands[0] = e0.expression;
f.operands[1] = e1.expression;
e.expression = f;
}
}
if (e.expression != null)
equations.add(e);
}
}
}
v.equations.clear();
}
use of gov.sandia.n2a.language.OperatorBinary in project n2a by frothga.
the class EquationSet method determineDuration.
/**
* Infers length of simulation based on contents of equation set, particularly
* an expression for top-level $p that involves $t.
* Depends on results of: determineTypes() -- to set up Variable.type member with usable values
*/
public void determineDuration() {
Variable p = find(new Variable("$p", 0));
if (p != null && p.equations.size() == 1) {
Operator expression = p.equations.first().expression;
Operator variable = null;
Operator value = null;
if (// only true if expression is not null
expression instanceof LT || expression instanceof LE) {
OperatorBinary comparison = (OperatorBinary) expression;
variable = comparison.operand0;
value = comparison.operand1;
} else if (expression instanceof GT || expression instanceof GE) {
OperatorBinary comparison = (OperatorBinary) expression;
variable = comparison.operand1;
value = comparison.operand0;
}
if (variable instanceof AccessVariable && ((AccessVariable) variable).name.equals("$t")) {
Instance instance = new Instance() {
// all AccessVariable objects will reach here first, and get back the Variable.type field
public Type get(VariableReference r) throws EvaluationException {
return r.variable.type;
}
};
Type result = value.eval(instance);
if (result instanceof Scalar)
setNamedValue("duration", new Double(((Scalar) result).value).toString());
}
}
}
Aggregations