#ifndef MAX_EXPRESSION_HPP #define MAX_EXPRESSION_HPP #include #include "Expression.hpp" #include "EquationSystem.hpp" #include "IdSet.hpp" template struct MaxStrategy { virtual ~MaxStrategy() { } virtual unsigned int get(const MaxExpression& e) { return const_cast*>(this)->get(e); } virtual unsigned int get(const MaxExpression& e) const = 0; }; unsigned int stack_depth = 1; std::string indent() { std::string result = ""; for (unsigned int i = 0; i < stack_depth; ++i) { result += '\t'; } return result; } #include "VariableAssignment.hpp" template struct DynamicVariableAssignment; template struct DynamicMaxStrategy : public MaxStrategy { DynamicMaxStrategy( const EquationSystem& system ) : _system(system), _rho(NULL), _values(system.maxExpressionCount(), 0), _stable(system.maxExpressionCount()), _influence(system.maxExpressionCount(), IdSet >(system.maxExpressionCount())) {} void setRho(DynamicVariableAssignment& rho) { _rho = ρ } unsigned int get(const MaxExpression& e) const { log::strategy << indent() << "Look up " << e << std::endl; return _values[e]; } unsigned int get(const MaxExpression& e) { log::strategy << indent() << "Solve for " << e << std::endl; solve(e); return _values[e]; } void invalidate(const MaxExpression& v) { if (_stable.contains(v)) { log::strategy << indent() << "Invalidating " << v << std::endl; //log::debug << indent() << " influence sets " << _influence << std::endl; _stable.remove(v); IdSet > infl = _influence[v]; for (typename IdSet >::iterator it = infl.begin(), end = infl.end(); it != end; ++it) { invalidate(_system.maxExpression(*it)); } } } private: void solve(const MaxExpression& x) { if (!_stable.contains(x)) { _stable.insert(x); log::strategy << indent() << "Stabilise " << x << std::endl; stack_depth++; DependencyAssignment assignment(*this, *_rho, x); DependencyStrategy depStrat(*this, x); unsigned int val = x.bestStrategy(assignment, depStrat, _values[x]); stack_depth--; if (val != _values[x]) { log::strategy << x << " => " << *x.arguments()[val] << std::endl; _values[x] = val; _rho->invalidate(*_system.varFromExpr(x)); //_rho->stabilise(); IdSet > infl = _influence[x]; _stable.filter(infl); for (typename IdSet >::iterator it = infl.begin(), end = infl.end(); it != end; ++it) { solve(_system.maxExpression(*it)); } } else { log::strategy << indent() << x << " did not change: " << x << " => " << *x.arguments()[val] << std::endl; } } else { log::strategy << indent() << x << " is stable: " << x << " => " << *x.arguments()[_values[x]] << std::endl; } } struct DependencyAssignment : public VariableAssignment{ DependencyAssignment(DynamicMaxStrategy& strat, DynamicVariableAssignment& rho, const MaxExpression& expr) : _strat(strat), _rho(rho), _expr(expr), _current(strat._system.variableCount()) { } const Domain operator[](const Variable& var) { // force evaluation to get touched variables Domain value = _rho[var]; _strat._influence[*_strat._system[var]].insert(_expr); // invalidate touched variables IdSet > changed = _rho.get_changed(); for (typename IdSet >::iterator it = changed.begin(), ei = changed.end(); it != ei; ++it) { _strat.invalidate(*_strat._system[_strat._system.variable(*it)]); } return value; } private: DynamicMaxStrategy& _strat; DynamicVariableAssignment& _rho; const MaxExpression& _expr; IdSet > _current; }; struct DependencyStrategy : public MaxStrategy { DependencyStrategy(DynamicMaxStrategy& strat, const MaxExpression& expr) : _strat(strat), _expr(expr) { } unsigned int get(const MaxExpression& e) const { _strat._influence[e].insert(_expr); return _strat._values[e]; } unsigned int get(const MaxExpression& e) { _strat.solve(e); _strat._influence[e].insert(_expr); return _strat._values[e]; } private: DynamicMaxStrategy& _strat; const MaxExpression& _expr; }; private: const EquationSystem& _system; DynamicVariableAssignment* _rho; IdMap,unsigned int> _values; IdSet > _stable; IdMap,IdSet > > _influence; }; template struct Solver { Solver(const EquationSystem& system) : _system(system), _strategy(system), _rho(_system, _strategy, -infinity()) { _strategy.setRho(_rho); } Domain solve(Variable& var) { MaxExpression& rhs = *_system[var]; // this will automatically work sufficiently to get the final // strategy for this variable's RHS _strategy.get(rhs); // this will automatically solve for the value of the RHS, if required return _rho[var]; } private: const EquationSystem& _system; DynamicMaxStrategy _strategy; DynamicVariableAssignment _rho; }; /*template std::ostream& operator<<(std::ostream& cout, const MaxStrategy& strat) { strat.print(cout); return cout; }*/ #endif