#ifndef MAX_EXPRESSION_HPP #define MAX_EXPRESSION_HPP #include "Expression.hpp" #include "EquationSystem.hpp" #include "IdSet.hpp" template struct MaxStrategy : public EquationSystem { MaxStrategy(const EquationSystem& sub) : _sub(sub) { } virtual ~MaxStrategy() { } virtual const Expression* operator[](const Variable& var) const { return _sub[var]; } virtual VariableAssignment* eval(const VariableAssignment& rho) const { return _sub.eval(rho); } virtual unsigned int variableCount() const { return _sub.variableCount(); } virtual Variable& variable(unsigned int i) const { return _sub.variable(i); } virtual StableVariableAssignment* assignment(const Domain& value) const { return _sub.assignment(value); } virtual bool equalAssignments(const VariableAssignment& r1, const VariableAssignment& r2) const { return _sub.equalAssignments(r1, r2); } virtual Variable* varFromExpr(const Expression& expr) const { return _sub.varFromExpr(expr); } virtual void print(std::ostream& cout) const { return _sub.print(cout); } virtual unsigned int get(const MaxExpression& e) const = 0; private: const EquationSystem& _sub; }; template struct MaxStrategyExpression : public Expression { MaxStrategyExpression(const Expression& expr, const MaxStrategy& 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.get(*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 MaxStrategy& _strategy; }; template struct ConcreteMaxStrategy : public MaxStrategy { ConcreteMaxStrategy(const ConcreteEquationSystem& system) : MaxStrategy(system), _system(system), _expressions(system.variableCount(), NULL), _strategy(system.maxExpressionCount(), 0) { } ~ConcreteMaxStrategy() { for (int i = 0, length = _system.variableCount(); i < length; ++i) { Expression* expr = _expressions[_system.variable(i)]; if (expr) delete expr; } } const Expression* operator[](const Variable& v) const { if (_expressions[v] == NULL) { Expression* expression = new MaxStrategyExpression(*_system[v], *this); _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); } unsigned int maxExpressionCount() const { return _system.maxExpressionCount(); } MaxExpression& maxExpression(unsigned int i) const { return _system.maxExpression(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 print(std::ostream& cout) const { cout << _system << std::endl; } const ConcreteEquationSystem& system() const { return _system; } const IdMap,unsigned int>& strategy() const { return _strategy; } private: const ConcreteEquationSystem& _system; mutable IdMap,Expression*> _expressions; IdMap,unsigned int> _strategy; }; #endif