#ifndef VARIABLE_ASSIGNMENT_HPP #define VARIABLE_ASSIGNMENT_HPP #include "Expression.hpp" #include "IdMap.hpp" template struct VariableAssignment { virtual ~VariableAssignment() { } virtual const Domain& operator[](const Variable&) const = 0; }; template struct StableVariableAssignment : public VariableAssignment, public IdMap, Domain> { StableVariableAssignment(unsigned int length) : IdMap,Domain>(length, -infinity()) { } StableVariableAssignment(unsigned int length, const Domain& value) : IdMap,Domain>(length, value) { } const Domain& operator[](const Variable& var) const { return IdMap,Domain>::operator[](var); } Domain& operator[](const Variable& var) { return IdMap,Domain>::operator[](var); } }; #include "EquationSystem.hpp" template struct DynamicMaxStrategy; template struct DynamicVariableAssignment : public VariableAssignment { DynamicVariableAssignment( const EquationSystem& system, const DynamicMaxStrategy& strat ) : _system(system), _strategy(strat), _values(system.variableCount(), infinity()), _stable(system.variableCount()), _influence(system.variableCount(), IdSet>(system.variableCount())) { } const Domain& operator[](const Variable& var) const { solve(var); return _values[var]; } void invalidate(const Variable& x) const { log::fixpoint << "invalidating " << x << std::endl; _stable.remove(x); _values[x] = infinity(); } 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]) { log::fixpoint << "Updating value for " << x << " to " << val << std::endl; auto oldInfluence = _influence[x]; _influence[x].clear(); _values[x] = val; _strategy.invalidate(x); _stable.filter(oldInfluence); for (auto it = oldInfluence.begin(); it != oldInfluence.end(); ++it) { solve(_system.variable(*it)); } } else { log::fixpoint << x << " did not change" << std::endl; } } else { log::fixpoint << x << " is stable" << std::endl; } } 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 DynamicMaxStrategy& _strategy; mutable StableVariableAssignment _values; mutable IdSet > _stable; mutable IdMap,IdSet > > _influence; }; #endif