#ifndef FIXPOINT_ALGORITHM_HPP #define FIXPOINT_ALGORITHM_HPP #include "VariableAssignment.hpp" template struct EquationSystem; template struct MaxStrategy; template struct FixpointAlgorithm { virtual VariableAssignment maxFixpoint(const MaxStrategy&, const EquationSystem&) const = 0; }; #include "EquationSystem.hpp" #include "MaxStrategy.hpp" template struct NaiveFixpoint : public FixpointAlgorithm { virtual VariableAssignment maxFixpoint(const MaxStrategy& strat, const EquationSystem& system) const { unsigned int size = system.varCount(); VariableAssignment newResult(size, infinity()); VariableAssignment result(0); do { result = newResult; newResult = strat(system, result); } while (newResult != result); return result; } }; template struct RecursiveFixpoint : public FixpointAlgorithm { // this is a "VariableAssignment" which actually performs a recursive // call to determine what value to return struct EvaluatingVariableAssignment : public VariableAssignment { EvaluatingVariableAssignment(const MaxStrategy& strategy, const EquationSystem& system) : VariableAssignment(system.varCount(), infinity()), _strategy(strategy), _system(system), _evaluating(NULL), _influence(system.varCount(), IdSet >(system.varCount())), _stable(system.varCount()) { } virtual T& operator[] (const Variable& x) const { if (_evaluating == NULL) { solve(x); return VariableAssignment::_assignment[x.id()]; } else { solve(x); _influence[x].insert(*_evaluating); return VariableAssignment::_assignment[x.id()]; } } void solve(const Variable& x) const { if (!_stable.contains(x)) { _stable.insert(x); const Variable* oldEval = _evaluating; _evaluating = &x; T t = _strategy(*_system[x], *this); _evaluating = oldEval; if (t != VariableAssignment::_assignment[x.id()]) { IdSet > oldInfluence = _influence[x]; _influence[x].clear(); // clear out our idea of what x influences VariableAssignment::_assignment[x.id()] = t; _stable.filter(oldInfluence); // whatever x influences needs to be re-evaluated for (typename IdSet >::iterator it = oldInfluence.begin(); it != oldInfluence.end(); ++it) { solve(*_system.getVar(*it)); } } } } private: const MaxStrategy& _strategy; const EquationSystem& _system; mutable const Variable* _evaluating; mutable IdMap, IdSet > > _influence; mutable IdSet > _stable; }; virtual VariableAssignment maxFixpoint(const MaxStrategy& strat, const EquationSystem& system) const { EvaluatingVariableAssignment assignment(strat, system); VariableAssignment result(system.varCount()); for (unsigned int i = 0; i < system.varCount(); ++i) { result[*system.getVar(i)] = assignment[*system.getVar(i)]; } return result; } }; #endif