Search in sources :

Example 1 with OperatorBinary

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();
}
Also used : Add(gov.sandia.n2a.language.operator.Add) Function(gov.sandia.n2a.language.Function) Divide(gov.sandia.n2a.language.operator.Divide) Min(gov.sandia.n2a.language.function.Min) Max(gov.sandia.n2a.language.function.Max) AND(gov.sandia.n2a.language.operator.AND) Multiply(gov.sandia.n2a.language.operator.Multiply) OperatorBinary(gov.sandia.n2a.language.OperatorBinary)

Example 2 with OperatorBinary

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());
        }
    }
}
Also used : Operator(gov.sandia.n2a.language.Operator) AccessVariable(gov.sandia.n2a.language.AccessVariable) AccessVariable(gov.sandia.n2a.language.AccessVariable) Instance(gov.sandia.n2a.language.type.Instance) LT(gov.sandia.n2a.language.operator.LT) GT(gov.sandia.n2a.language.operator.GT) OperatorBinary(gov.sandia.n2a.language.OperatorBinary) Scalar(gov.sandia.n2a.language.type.Scalar) Type(gov.sandia.n2a.language.Type) LE(gov.sandia.n2a.language.operator.LE) GE(gov.sandia.n2a.language.operator.GE)

Aggregations

OperatorBinary (gov.sandia.n2a.language.OperatorBinary)2 AccessVariable (gov.sandia.n2a.language.AccessVariable)1 Function (gov.sandia.n2a.language.Function)1 Operator (gov.sandia.n2a.language.Operator)1 Type (gov.sandia.n2a.language.Type)1 Max (gov.sandia.n2a.language.function.Max)1 Min (gov.sandia.n2a.language.function.Min)1 AND (gov.sandia.n2a.language.operator.AND)1 Add (gov.sandia.n2a.language.operator.Add)1 Divide (gov.sandia.n2a.language.operator.Divide)1 GE (gov.sandia.n2a.language.operator.GE)1 GT (gov.sandia.n2a.language.operator.GT)1 LE (gov.sandia.n2a.language.operator.LE)1 LT (gov.sandia.n2a.language.operator.LT)1 Multiply (gov.sandia.n2a.language.operator.Multiply)1 Instance (gov.sandia.n2a.language.type.Instance)1 Scalar (gov.sandia.n2a.language.type.Scalar)1