#ifndef MAX_EXPRESSION_HPP #define MAX_EXPRESSION_HPP #include "Expression.hpp" #include "EquationSystem.hpp" template struct MaxStrategyExpression : public Expression { MaxStrategyExpression(const Expression& expr, const IdMap,unsigned int>& strategy) : _expr(expr), _strategy(strategy) { } virtual Domain eval(const VariableAssignment& rho) const { // relies on implementation details - BAD BAD BAD, maybe const OperatorExpression* opExpr = dynamic_cast*>(&_expr); if (opExpr) { const MaxExpression* maxExpr = dynamic_cast*>(opExpr); const std::vector*> args = opExpr->arguments(); if (maxExpr) { unsigned int i = _strategy[*maxExpr]; return MaxStrategyExpression(*args[i], _strategy).eval(rho); } else { std::vector argumentValues; for (typename std::vector*>::const_iterator it = args.begin(); it != args.end(); ++it) { argumentValues.push_back(MaxStrategyExpression(**it, _strategy).eval(rho)); } return opExpr->op().eval(argumentValues); } } else { return _expr.eval(rho); } } void print(std::ostream& cout) const { cout << _expr; } private: const Expression& _expr; const IdMap,unsigned int>& _strategy; }; template struct MaxStrategy : public EquationSystem { MaxStrategy(const ConcreteEquationSystem& system) : _system(system), _expressions(system.variableCount(), NULL), _strategy(system.maxExpressionCount(), 0) { } const Expression* operator[](const Variable& v) const { if (_expressions[v] == NULL) { Expression* expression = new MaxStrategyExpression(*_system[v], _strategy); _expressions[v] = expression; return expression; } else { return _expressions[v]; } } unsigned int get(const MaxExpression& e) const { return _strategy[e]; } unsigned int set(const MaxExpression& e, unsigned int i) { _strategy[e] = i; return i; } VariableAssignment* eval(const VariableAssignment& rho) const { StableVariableAssignment* result = this->assignment(-infinity()); for (unsigned int i = 0, length = _system.variableCount(); i < length; ++i) { const Variable& var = _system.variable(i); const Expression& expr = * (*this)[var]; (*result)[var] = expr.eval(rho); } return result; } unsigned int variableCount() const { return _system.variableCount(); } Variable& variable(unsigned int i) const { return _system.variable(i); } StableVariableAssignment* assignment(const Domain& v) const { return _system.assignment(v); } bool equalAssignments(const VariableAssignment& l, const VariableAssignment& r) const { return _system.equalAssignments(l, r); } void improve(const VariableAssignment& rho) { for (unsigned int i = 0, length = _system.maxExpressionCount(); i < length; ++i) { MaxExpression& expr = _system.maxExpression(i); Domain bestValue = MaxStrategyExpression(expr, _strategy).eval(rho); unsigned int bestIndex = this->get(expr); // this relies on the fact that an expression will only be proessed after the expressions // it depends on (which should always be true, as they form a DAG) const std::vector*> args = expr.arguments(); for (unsigned int j = 0, length = args.size(); j < length; ++j) { const Domain value = MaxStrategyExpression(*args[j], _strategy).eval(rho); if (bestValue < value) { bestValue = value; bestIndex = j; } } this->set(expr, bestIndex); } } void print(std::ostream& cout) const { cout << _system << std::endl; } private: const ConcreteEquationSystem& _system; mutable IdMap,Expression*> _expressions; IdMap,unsigned int> _strategy; }; #endif