#ifndef MAX_EXPRESSION_HPP #define MAX_EXPRESSION_HPP #include "Expression.hpp" #include "EquationSystem.hpp" #include "IdSet.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) { } ~MaxStrategy() { 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], _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); } struct ImprovementOperator { virtual ~ImprovementOperator() { } virtual bool improve( MaxStrategy& strat, const VariableAssignment& rho, const IdSet >& changedIn, IdSet >& changedOut ) const = 0; }; bool improve(const ImprovementOperator& op, const VariableAssignment& rho, const IdSet >& changedIn, IdSet >& changedOut) { return op.improve(*this, rho, changedIn, changedOut); } struct NaiveImprovementOperator : public ImprovementOperator { bool improve( MaxStrategy& strat, const VariableAssignment& rho, const IdSet >& changedIn, IdSet >& changedOut ) const { bool changed = false; for (unsigned int i = 0, length = strat._system.maxExpressionCount(); i < length; ++i) { MaxExpression& expr = strat._system.maxExpression(i); Domain bestValue = MaxStrategyExpression(expr, strat._strategy).eval(rho); unsigned int lastIndex= strat.get(expr); unsigned int bestIndex = strat.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], strat._strategy).eval(rho); if (bestValue < value) { bestValue = value; bestIndex = j; } } if (bestIndex != lastIndex) { changed = true; strat.set(expr, bestIndex); } } return changed; } }; struct RepeatedImprovementOperator : public ImprovementOperator { RepeatedImprovementOperator(const ImprovementOperator& op) : _subImprovement(op) { } bool improve( MaxStrategy& strat, const VariableAssignment& rho, const IdSet >& changedIn, IdSet >& changedOut ) const { if (_subImprovement.improve(strat, rho, changedIn, changedOut)) { VariableAssignment* rho2 = strat.eval(rho); improve(strat, *rho2, changedIn, changedOut); delete rho2; return true; } return false; } private: const ImprovementOperator& _subImprovement; }; struct DependencyImprovementOperator : public ImprovementOperator { }; void print(std::ostream& cout) const { cout << _system << std::endl; } private: const ConcreteEquationSystem& _system; mutable IdMap,Expression*> _expressions; IdMap,unsigned int> _strategy; }; #endif