#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& x) = 0; }; #include "EquationSystem.hpp" template struct DynamicMaxStrategy; template struct DynamicVariableAssignment : public VariableAssignment { DynamicVariableAssignment( const EquationSystem& system, DynamicMaxStrategy& strat, const Domain& value=infinity() ) : _system(system), _strategy(strat), _values(system.variableCount(), value), _old_values(system.variableCount(), value), _unstable(system.variableCount()), _influence(system.variableCount(), IdSet >(system.variableCount())), _touched(system.variableCount()) { } const Domain operator[](const Variable& var) { solve(var); return _values[var]; } void invalidate(const Variable& x) { if (!_unstable.contains(x)) { log::fixpoint << indent() << "Invalidating " << x << std::endl; _unstable.insert(x); _touched.insert(x); _old_values[x] = _values[x]; _values[x] = infinity(); IdSet > infl = _influence[x]; _influence[x].clear(); for (typename IdSet >::iterator it = infl.begin(), ei = infl.end(); it != ei; ++it) { invalidate(_system.variable(*it)); } } } IdSet > get_changed() { IdSet > changed; if (_touched.size() > 0) { for (typename IdSet >::iterator it = _touched.begin(), ei = _touched.end(); it != ei; ++it) { Variable& var = _system.variable(*it); if (!_unstable.contains(var) && _old_values[var] != _values[var]) { changed.insert(var); _touched.remove(var); } } } //_touched.clear(); return changed; } private: void solve(const Variable& x) { if (_unstable.contains(x)) { _unstable.remove(x); log::fixpoint << indent() << "Stabilise " << x << std::endl; stack_depth++; // we don't want the assignment to affect the strategy, so we're // going to use a const reference here const DynamicMaxStrategy& const_strat = _strategy; DependencyAssignment assignment(*this, x); Domain val = _system[x]->eval(assignment, const_strat); if (val != _values[x]) { log::fixpoint << x << " = " << val << std::endl; IdSet > oldInfluence = _influence[x]; _influence[x].clear(); _values[x] = val; _unstable.absorb(oldInfluence); for (typename IdSet >::iterator it = oldInfluence.begin(); it != oldInfluence.end(); ++it) { solve(_system.variable(*it)); } } else { log::fixpoint << indent() << x << " did not change: " << x << " = " << val << std::endl; } stack_depth--; } else { log::fixpoint << indent() << x << " is stable: " << x << " = " << _values[x] << std::endl; } } struct DependencyAssignment : public VariableAssignment { DependencyAssignment(DynamicVariableAssignment& assignment, const Variable& var) : _assignment(assignment), _var(var) { } const Domain operator[](const Variable& x) { const Domain result = _assignment[x]; _assignment._influence[x].insert(_var); return result; } private: DynamicVariableAssignment& _assignment; const Variable& _var; }; const EquationSystem& _system; DynamicMaxStrategy& _strategy; IdMap, Domain> _values; IdMap, Domain> _old_values; IdSet > _unstable; IdMap,IdSet > > _influence; IdSet > _touched; }; #endif