Пример #1
0
bool Recurrence::calcIteratedUpdate(const UpdateMap &oldUpdate, const Expression &meterfunc, UpdateMap &newUpdate) {
    assert(newUpdate.empty());

    UpdateMap update = oldUpdate; //might be changed by dependencyOrder, so copy here
    vector<VariableIndex> order = dependencyOrder(update);
    assert(order.size() == update.size());

    //in the given order try to solve the recurrence for every updated variable
    for (VariableIndex vi : order) {
        Expression res;
        ExprSymbol target = itrs.getGinacSymbol(vi);

        //use update rhs, but replace already processed variables with their recurrences
        Expression todo = update.at(vi).subs(knownPreRecurrences);
        if (!findUpdateRecurrence(todo,target,res)) {
            return false;
        }

        //remember this recurrence to replace vi in the updates depending on vi
        //note that updates need the value at n-1, e.g. x(n) = x(n-1) + vi(n-1) for the update x=x+vi
        knownPreRecurrences[target] = res.subs(ginacN == ginacN-1);

        //calcuate the final update using the loop's runtime
        newUpdate[vi] = res.subs(ginacN == meterfunc);
    }

    return true;
}
Пример #2
0
//NOTE: very stupid and not very efficient; better use a graph for this problem
vector<VariableIndex> Recurrence::dependencyOrder(UpdateMap &update) {
    vector<VariableIndex> ordering;
    set<VariableIndex> orderedVars;

    while (ordering.size() < update.size()) {
        bool changed = false;
        for (auto up : update) {
            if (orderedVars.count(up.first) > 0) continue;

            //check if all variables on update rhs are already processed
            for (const string &varname : up.second.getVariableNames()) {
                VariableIndex vi = itrs.getVarindex(varname);
                if (vi != up.first && update.count(vi) > 0 && orderedVars.count(vi) == 0)
                    goto skipUpdate;
            }

            orderedVars.insert(up.first);
            ordering.push_back(up.first);
            changed = true;

            skipUpdate: ;
        }

        if (changed) continue;

        //if not all dependencies could be resolved, try to add constraints to the guard to make things easier
        GiNaC::exmap subs;
        ExprSymbol target;
        bool has_target = false;
        for (auto up : update) {
            if (orderedVars.count(up.first) > 0) continue;
            if (!has_target) {
                target = itrs.getGinacSymbol(up.first);
                has_target = true;
            } else {
                addGuard.push_back(target == itrs.getGinacSymbol(up.first));
                subs[itrs.getGinacSymbol(up.first)] = target;
            }
        }
        //assume all remaining variables are equal
        for (auto &up : update) {
            up.second = up.second.subs(subs);
        }
    }
    return ordering;
}