#ifndef FIXPOINT_ALGORITHM_HPP #define FIXPOINT_ALGORITHM_HPP #include "IdSet.hpp" #include "IdMap.hpp" #include "VariableAssignment.hpp" #include "EquationSystem.hpp" template struct FixpointAlgorithm { virtual ~FixpointAlgorithm() { } virtual VariableAssignment* maxFixpoint(const EquationSystem&) const = 0; }; template struct NaiveFixpointAlgorithm : public FixpointAlgorithm { virtual VariableAssignment* maxFixpoint(const EquationSystem& system) const { VariableAssignment* rho = NULL; VariableAssignment* result = system.assignment(infinity()); do { if (rho) delete rho; rho = result; result = system.eval(*rho); } while (!system.equalAssignments(*rho, *result)); if (rho) delete rho; return result; } }; template struct SmartFixpointAlgorithm : public FixpointAlgorithm { struct DynamicVariableAssignment : public VariableAssignment { DynamicVariableAssignment(const EquationSystem& system) : _system(system), _evaluating(NULL), _values(system.variableCount(), infinity()), _stable(system.variableCount()), _haveValue(system.variableCount()), _influence(system.variableCount(), IdSet >(system.variableCount())) { } const Domain& operator[](const Variable& var) const { solve(var); return _values[var]; } private: void solve(const Variable& x) const { if (!_stable.contains(x)) { _stable.insert(x); Domain val = _system[x]->eval(DependencyAssignment(*this, x)); if (val != _values[x]) { IdSet > oldInfluence = _influence[x]; _influence[x].clear(); _values[x] = val; _stable.filter(oldInfluence); for (typename IdSet >::iterator it = oldInfluence.begin(); it != oldInfluence.end(); ++it) { solve(_system.variable(*it)); } } } } struct DependencyAssignment : public VariableAssignment { DependencyAssignment(const DynamicVariableAssignment& assignment, const Variable& var) : _assignment(assignment), _var(var) { } const Domain& operator[](const Variable& x) const { const Domain& result = _assignment[x]; _assignment._influence[x].insert(_var); return result; } private: const DynamicVariableAssignment& _assignment; const Variable& _var; }; const EquationSystem& _system; mutable const Variable* _evaluating; mutable IdMap,Domain> _values; mutable IdSet > _stable; mutable IdSet > _haveValue; mutable IdMap,IdSet > > _influence; }; virtual VariableAssignment* maxFixpoint(const EquationSystem& system) const { return new DynamicVariableAssignment(system); } }; #endif