.. _program_listing_file_src_VALfiles_FuncAnalysis.h: Program Listing for File FuncAnalysis.h ======================================= |exhale_lsh| :ref:`Return to documentation for file ` (``src/VALfiles/FuncAnalysis.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /************************************************************************ * Copyright 2008, Strathclyde Planning Group, * Department of Computer and Information Sciences, * University of Strathclyde, Glasgow, UK * http://planning.cis.strath.ac.uk/ * * Maria Fox, Richard Howey and Derek Long - VAL * Stephen Cresswell - PDDL Parser * * This file is part of VAL, the PDDL validator. * * VAL is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * VAL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VAL. If not, see . * ************************************************************************/ #ifndef __FUNCANALYSIS #define __FUNCANALYSIS #include #include #include #include #include using std::vector; using std::pair; using std::make_pair; using std::ostream; using std::max; using std::min; namespace VAL { class extended_func_symbol; typedef std::map > IGraph; }; #include "VisitController.h" namespace VAL { extern bool FAverbose; enum FValueEnum {E_POSITIVE=0,E_NEGATIVE=1,E_NONNEG=2, E_NONPOS=3,E_ZERO=4,E_ALL=5,E_BOUNDED=6}; class FValue { private: FValueEnum fve; bool isConst; public: FValue() : fve(E_POSITIVE), isConst(false) {}; FValue(FValueEnum e) : fve(e), isConst(false) {}; FValue(int e) : fve((FValueEnum)(e)), isConst(false) {}; FValue(const FValue & f) : fve(f.fve), isConst(f.isConst) {}; operator FValueEnum() const {return fve;}; bool isConstant() const {return isConst;}; int toInt() const {return fve;}; void assertConst() {isConst = true;}; }; void operator+=(FValue & f1,FValue f2); void operator*=(FValue & f1,FValue f2); void operator-=(FValue & f1,FValue f2); void operator/=(FValue & f1,FValue f2); FValue operator-(FValue & f1); inline ostream & operator<<(ostream & o,FValue fv) { switch(fv) { case E_POSITIVE: o << "strictly positive"; break; case E_NEGATIVE: o << "strictly negative"; break; case E_NONNEG: o << "non-negative"; break; case E_NONPOS: o << "non-positive"; break; case E_ZERO: o << "initially zero"; break; case E_ALL: o << "fluctuating"; break; default: break; }; return o; }; class FuncGatherer : public VisitController { private: extended_func_symbol * eft; bool cont; public: FuncGatherer(extended_func_symbol * e) : eft(e), cont(false) {}; virtual void visit_plus_expression(plus_expression * p) { p->getLHS()->visit(this); p->getRHS()->visit(this); }; virtual void visit_minus_expression(minus_expression * p) { p->getLHS()->visit(this); p->getRHS()->visit(this); }; virtual void visit_mul_expression(mul_expression * p) { p->getLHS()->visit(this); p->getRHS()->visit(this); }; virtual void visit_div_expression(div_expression * p) { p->getLHS()->visit(this); p->getRHS()->visit(this); }; virtual void visit_uminus_expression(uminus_expression * p) { p->getExpr()->visit(this); }; virtual void visit_func_term(func_term * p); virtual void visit_assignment(assignment * p) { p->getExpr()->visit(this); }; virtual void visit_special_val_expr(special_val_expr * s) { cont = true; }; bool isCont() const { return cont; }; }; typedef pair Updater; typedef vector Updates; class extended_func_symbol : public func_symbol { protected: vector > preconds; vector initials; Updates assigns; Updates increasers; Updates decreasers; Updates scalers; Updates continuous; vector dependencies; bool seenPos; bool seenNeg; bool seenZero; bool difficultInitial; double top; double bottom; mutable FValue cval; int goals; public: virtual ~extended_func_symbol() {}; extended_func_symbol(const string & nm) : func_symbol(nm), seenPos(false), seenNeg(false), seenZero(false), difficultInitial(false), goals(0) {}; void addInitial(assignment * a) { initials.push_back(a); const num_expression * nm = dynamic_cast((a)->getExpr()); if(!nm) { difficultInitial = true; return; }; double d = nm->double_value(); if(seenPos || seenNeg || seenZero) { top = max(top,d); bottom = min(bottom,d); } else { top = d; bottom = d; }; seenPos |= (d>0); seenNeg |= (d<0); seenZero |= (d==0); }; void addPre(operator_* o) { preconds.push_back(pair(o,0)); }; void addPre(derivation_rule * o) { preconds.push_back(pair(0,o)); }; void addAssign(operator_ * o,assignment * a) { assigns.push_back(make_pair(o,a)); FuncGatherer fg(this); a->visit(&fg); }; void addIncreaser(operator_ * o,assignment * a) { FuncGatherer fg(this); a->visit(&fg); if(fg.isCont()) { continuous.push_back(make_pair(o,a)); } else { increasers.push_back(make_pair(o,a)); }; }; bool onlyGoingDown() { return assigns.empty() && increasers.empty() && !decreasers.empty() && scalers.empty() && continuous.empty(); } bool onlyGoingUp() { return assigns.empty() && !increasers.empty() && decreasers.empty() && scalers.empty() && continuous.empty(); } void addContinuous(operator_ * o,assignment * a) { continuous.push_back(make_pair(o,a)); }; void addDecreaser(operator_ * o,assignment * a) { FuncGatherer fg(this); a->visit(&fg); if(fg.isCont()) { continuous.push_back(make_pair(o,a)); } else { decreasers.push_back(make_pair(o,a)); }; }; void addOther(operator_ * o,assignment * a) { scalers.push_back(make_pair(o,a)); FuncGatherer fg(this); a->visit(&fg); }; void addDepend(extended_func_symbol * e) { dependencies.push_back(e); }; void addGoal() {++goals;}; bool isStatic() const { return assigns.empty() && increasers.empty() && decreasers.empty() && scalers.empty() && continuous.empty(); }; bool isDiscrete() const { return continuous.empty(); }; bool isContinuous() const { return !continuous.empty(); }; FValue initially() const { if(difficultInitial) { return (cval = E_ALL); }; if(!seenPos) { if(!seenZero) return (cval = E_NEGATIVE); if(seenNeg) return (cval = E_NONPOS); return (cval = E_ZERO); } else if(!seenNeg) { if(seenZero) return (cval = E_NONNEG); return (cval = E_POSITIVE); }; return (cval = E_ZERO); }; FValue currently() const { return cval; }; void applyUpdates(); void write(ostream & o) const { o << "Report for: " << getName() << "\n"; o << "Preconditions:\n"; for(vector >::const_iterator i = preconds.begin(); i != preconds.end();++i) { if(i->first) o << "\t" << i->first->name->getName() << "\n"; if(i->second) o << "\t" << i->second->get_head()->head->getName() << "\n"; }; if(isStatic()) { o << "Fluent is static\n"; } else if(assigns.empty() && scalers.empty()) { if(increasers.empty() || decreasers.empty()) { o << "Could be a one way changing value\n"; } else { o << "Seems to be an additive tracking quantity\n"; }; o << "Assigns:\n"; for(Updates::const_iterator i = assigns.begin(); i != assigns.end();++i) { if(i->first) o << "\t" << i->first->name->getName() << "\n"; }; o << "Increasers:\n"; for(Updates::const_iterator i = increasers.begin(); i != increasers.end();++i) { if(i->first) o << "\t" << i->first->name->getName() << "\n"; }; o << "Decreasers:\n"; for(Updates::const_iterator i = decreasers.begin(); i != decreasers.end();++i) { if(i->first) o << "\t" << i->first->name->getName() << "\n"; }; o << "Scalers:\n"; for(Updates::const_iterator i = scalers.begin(); i != scalers.end();++i) { if(i->first) o << "\t" << i->first->name->getName() << "\n"; }; if(!continuous.empty()) { o << "Continuous value, affected by:\n"; for(Updates::const_iterator i = continuous.begin(); i != continuous.end();++i) { if(i->first) o << "\t" << i->first->name->getName() << "\n"; }; }; }; o << "Initial value assignments:\n"; for(vector::const_iterator i = initials.begin(); i != initials.end();++i) { o << "\t(" << getName(); for(parameter_symbol_list::const_iterator j = (*i)->getFTerm()->getArgs()->begin();j != (*i)->getFTerm()->getArgs()->end();++j) { o << " " << (*j)->getName(); }; o << ") = " << dynamic_cast((*i)->getExpr())->double_value() << "\n"; }; if(isStatic()) { o << "Noting"; } else { o << "Dependencies:\n"; for(vector::const_iterator i = dependencies.begin(); i != dependencies.end();++i) { o << "\t" << (*i)->getName() << "\n"; }; o << "Speculating"; }; o << " that this value is: " << initially() << "\n"; if(goals) { o << "Value appears in " << goals << " goals\n"; }; }; void set(FValue f) {cval = f;}; FValue get() const {return cval;}; void visit(VisitController * v) const { write(cout); }; const vector & getDeps() const { return dependencies; }; template pair getInitial(const TI t1,const TI) const { // A CascadeMap would be better. vector::const_iterator i = initials.begin(); const vector::const_iterator iEnd = initials.end(); for(;i != iEnd;++i) { const parameter_symbol_list * const argList = (*i)->getFTerm()->getArgs(); parameter_symbol_list::const_iterator j = argList->begin(); const parameter_symbol_list::const_iterator jEnd = argList->end(); TI localt1 = t1; for(;j != jEnd;++j,++localt1) { if((*j)!=*localt1) break; }; if(j == jEnd) { return make_pair(true,dynamic_cast((*i)->getExpr())->double_value()); }; }; return make_pair(false,0); // Probably better if this threw an exception }; typedef vector::const_iterator const_iterator; const_iterator begin() const {return initials.begin();}; const_iterator end() const {return initials.end();}; }; #define EFT(x) static_cast(const_cast(x)) class FuncAnalysis { private: typedef vector > Dependencies; Dependencies deps; template void doExplore(std::set & explored, vector & tsort, bool invert,IGraph & inverted,extended_func_symbol * fn,TI,TI); void exploreFrom(std::set & explored, vector & tsort, bool invert,IGraph & inverted,func_symbol * fn); public: FuncAnalysis(func_symbol_table & ftab); // To call after the visitor has set up the initial dependencies // in the extended_func_symbols. }; class AbstractEvaluator : public VisitController { private: FValue val; public: AbstractEvaluator() : val(E_ALL) {}; virtual void visit_plus_expression(plus_expression * p) { p->getLHS()->visit(this); FValue val1 = val; p->getRHS()->visit(this); val += val1; }; virtual void visit_minus_expression(minus_expression * p) { p->getRHS()->visit(this); FValue val1 = val; p->getLHS()->visit(this); val -= val1; }; virtual void visit_mul_expression(mul_expression * p) { p->getLHS()->visit(this); FValue val1 = val; p->getRHS()->visit(this); val *= val1; }; virtual void visit_div_expression(div_expression * p) { p->getRHS()->visit(this); FValue val1 = val; p->getLHS()->visit(this); val /= val1; }; virtual void visit_uminus_expression(uminus_expression * p) { p->getExpr()->visit(this); val = -val; }; virtual void visit_func_term(func_term * p) { val = EFT(p->getFunction())->currently(); if(EFT(p->getFunction())->isStatic()) { val.assertConst(); }; }; virtual void visit_int_expression(int_expression * p) { double d = p->double_value(); if(d < 0) { val = E_NEGATIVE; } else if(d > 0) { val = E_POSITIVE; } else { val = E_ZERO; }; val.assertConst(); }; virtual void visit_float_expression(float_expression * p) { double d = p->double_value(); if(d < 0) { val = E_NEGATIVE; } else if(d > 0) { val = E_POSITIVE; } else { val = E_ZERO; }; val.assertConst(); }; FValue operator()() {return val;}; }; }; #endif