#ifndef FIXPOINT_ALGORITHM_HPP #define FIXPOINT_ALGORITHM_HPP #include "IdSet.hpp" #include "IdMap.hpp" #include "VariableAssignment.hpp" #include "EquationSystem.hpp" #include "MaxStrategy.hpp" template struct FixpointAlgorithm { virtual ~FixpointAlgorithm() { } virtual void maxFixpoint( const EquationSystem& system, const MaxStrategy& strat, StableVariableAssignment& rho, IdSet >& changedIn, IdSet >& changedOut ) = 0; }; template struct NaiveFixpointAlgorithm : public FixpointAlgorithm { NaiveFixpointAlgorithm(const EquationSystem& system) : _system(system) { } virtual void maxFixpoint( const EquationSystem& system, const MaxStrategy& strat, StableVariableAssignment& rhoOut, IdSet >&, IdSet >& ) { VariableAssignment* rho = NULL; VariableAssignment* result = system.assignment(infinity()); do { if (rho) delete rho; rho = result; result = _system.eval(*rho, strat); } while (!_system.equalAssignments(*rho, *result)); if (rho) delete rho; for (unsigned int i = 0, length = system.variableCount(); i < length; ++i) { Variable var = system.variable(i); rhoOut[var] = (*result)[var]; } } private: const EquationSystem& _system; }; template struct SmartFixpointAlgorithm : public FixpointAlgorithm { SmartFixpointAlgorithm(const EquationSystem& system) : _system(system), _influence(system.variableCount(), IdSet >(system.variableCount())){ } struct DynamicVariableAssignment : public VariableAssignment { DynamicVariableAssignment( const EquationSystem& system, const MaxStrategy& strat, IdMap,IdSet > >& influence, StableVariableAssignment& rho, IdSet >& stable, IdSet >& changed ) : _system(system), _strategy(strat), _values(rho), _stable(stable), _changed(changed), _influence(influence) { } 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), _strategy); if (val != _values[x]) { IdSet > oldInfluence = _influence[x]; _influence[x].clear(); _values[x] = val; _changed.insert(x); _stable.filter(oldInfluence); for (typename IdSet >::iterator it = oldInfluence.begin(); it != oldInfluence.end(); ++it) { solve(_system.variable(*it)); } _influence[x] = oldInfluence; } } } 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; const MaxStrategy& _strategy; StableVariableAssignment& _values; IdSet >& _stable; IdSet >& _changed; IdMap,IdSet > >& _influence; }; void invalidate(const IdSet >& set, IdSet >& changed, StableVariableAssignment& rho) const { for (typename IdSet >::iterator it = set.begin(), end = set.end(); it != end; ++it) { Variable& var = _system.variable(*it); if (!changed.contains(var)) { rho[var] = infinity(); changed.insert(var); invalidate(_influence[var], changed, rho); } } } virtual void maxFixpoint( const EquationSystem& system, const MaxStrategy& strat, StableVariableAssignment& rhoOut, IdSet >& changedIn, IdSet >& changedOut ) { for (typename IdSet >::iterator it = changedIn.begin(), end = changedIn.end(); it != end; ++it) { //std::cout << *it << " "; Variable& var = _system.variable(*it); rhoOut[var] = infinity(); invalidate(_influence[var], changedIn, rhoOut); } changedIn.invert(); DynamicVariableAssignment rho(system, strat, _influence, rhoOut, changedIn, changedOut); for (unsigned int i = 0, length = system.variableCount(); i < length; ++i) { rho[system.variable(i)]; } /*std::cout << _influence << std::endl; std::cout << std::endl;*/ } private: const EquationSystem& _system; IdMap,IdSet > > _influence; }; #endif