Search in sources :

Example 1 with Min

use of gov.sandia.n2a.language.function.Min 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)

Aggregations

Function (gov.sandia.n2a.language.Function)1 OperatorBinary (gov.sandia.n2a.language.OperatorBinary)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 Multiply (gov.sandia.n2a.language.operator.Multiply)1