Program Listing for File Domain.h

Return to documentation for file (/tmp/ws/src/ros2_planning_system/plansys2_pddl_parser/include/plansys2_pddl_parser/Domain.h)

#pragma once

  #include "plansys2_pddl_parser/Task.h"
  #include "plansys2_pddl_parser/TemporalAction.h"
  #include "plansys2_pddl_parser/And.h"
  #include "plansys2_pddl_parser/Derived.h"
  #include "plansys2_pddl_parser/Exists.h"
  #include "plansys2_pddl_parser/Forall.h"
  #include "plansys2_pddl_parser/Function.h"
  #include "plansys2_pddl_parser/GroundFunc.h"
  #include "plansys2_pddl_parser/FunctionModifier.h"

  #include "plansys2_pddl_parser/Not.h"
  #include "plansys2_pddl_parser/Oneof.h"
  #include "plansys2_pddl_parser/Or.h"
  #include "plansys2_pddl_parser/EitherType.h"
  #include "plansys2_pddl_parser/When.h"

#define DOMAIN_DEBUG false

namespace parser { namespace pddl {

class Domain {
public:

    std::string name;                   // name of domain

    bool equality;                      // whether domain supports equality
    bool strips, adl, condeffects;      // whether domain is strips, adl and/or has conditional effects
    bool typed, cons, costs;            // whether domain is typed, has constants, has costs
    bool temp, nondet, neg, disj;       // whether domain is temporal, is non-deterministic, has negative precons, has disjunctive preconditions
    bool universal;                     // whether domain has universal precons
    bool fluents;                       // whether domains contains fluents
    bool derivedpred;                   // whether domain contains derived predicates

    TokenStruct< Type * > types;        // types
    TokenStruct< Lifted * > preds;      // predicates
    TokenStruct< Function * > funcs;    // functions
    TokenStruct< Action * > actions;    // actions
    TokenStruct< Derived * > derived;   // derived predicates
    TokenStruct< Task * > tasks;        // tasks

    Domain()
        : equality( false ), strips( false ), adl( false ), condeffects( false )
        , typed( false ), cons( false ), costs( false ), temp( false )
        , nondet( false ), neg( false ), disj( false ), universal( false )
        , fluents( false ), derivedpred( false )
    {
        types.insert( new Type( "object" ) ); // Type 0 is always "object", whether the domain is typed or not
    }

    Domain( const std::string & s ) : Domain()
    {
        parse( s );
    }

    virtual ~Domain() {
        for ( unsigned i = 0; i < types.size(); ++i )
            delete types[i];
        for ( unsigned i = 0; i < preds.size(); ++i )
            delete preds[i];
        for ( unsigned i = 0; i < funcs.size(); ++i )
            delete funcs[i];
        for ( unsigned i = 0; i < actions.size(); ++i )
            delete actions[i];
        for ( unsigned i = 0; i < derived.size(); ++i )
            delete derived[i];
        for ( unsigned i = 0; i < tasks.size(); ++i )
            delete tasks[i];
    }

    virtual void parse( const std::string & s ) {
        Stringreader f( s );
        name = f.parseName( "domain" );

        if ( DOMAIN_DEBUG ) std::cout << name << "\n";

        for ( ; f.getChar() != ')'; f.next() ) {
            f.assert_token( "(" );
            f.assert_token( ":" );
            std::string t = f.getToken();

            if ( DOMAIN_DEBUG ) std::cout << t << "\n";

            if (!parseBlock(t, f)) {
                f.tokenExit( t );
            }
        }
    }

    virtual bool parseBlock(const std::string& t, Stringreader& f) {
        if ( t == "requirements" ) parseRequirements( f );
        else if ( t == "types" ) parseTypes( f );
        else if ( t == "constants" ) parseConstants( f );
        else if ( t == "predicates" ) parsePredicates( f );
        else if ( t == "functions" ) parseFunctions( f );
        else if ( t == "action" ) parseAction( f );
        else if ( t == "durative-action" ) parseDurativeAction( f );
        else if ( t == "derived" ) parseDerived( f );
//      else if ( t == "axiom" ) parseAxiom( f );
        else return false; // Unknown block type

        return true;
    }


    void parseRequirements( Stringreader & f ) {
        for ( f.next(); f.getChar() != ')'; f.next() ) {
            f.assert_token( ":" );
            std::string s = f.getToken();

            if ( DOMAIN_DEBUG ) std::cout << "  " << s << "\n";

            if (!parseRequirement(s)) {
                f.tokenExit( s );
            }
        }

        ++f.c;
    }

    virtual bool parseRequirement( const std::string& s ) {
        if ( s == "strips" ) strips = true;
        else if ( s == "adl" ) adl = true;
        else if ( s == "negative-preconditions" ) neg = true;
        else if ( s == "conditional-effects" ) condeffects = true;
        else if ( s == "typing" ) typed = true;
        else if ( s == "action-cost" ) costs = true;
        else if ( s == "equality" ) equality = true;
        else if ( s == "durative-actions" ) temp = true;
        else if ( s == "non-deterministic" ) nondet = true;
        else if ( s == "universal-preconditions" ) universal = true;
        else if ( s == "fluents" ) fluents = true;
        else if ( s == "disjuntive-preconditions" ) disj = true;
        else if ( s == "derived-predicates" ) derivedpred = true;
        else return false; // Unknown requirement

        return true;
    }

    // get the type corresponding to a string
    Type * getType( std::string s ) {
        int i = types.index( s );
        if ( i < 0 ) {
            if ( s[0] == '(' ) {
                i = types.insert( new EitherType( s ) );
                for ( unsigned k = 9; s[k] != ')'; ) {
                    unsigned e = s.find( ' ', k );
                    types[i]->subtypes.push_back( getType( s.substr( k, e - k ) ) );
                    k = e + 1;
                }
            }
            else i = types.insert( new Type( s ) );
        }
        return types[i];
    }

    // convert a vector of type names to integers
    IntVec convertTypes( const StringVec & v ) {
        IntVec out;
        for ( unsigned i = 0; i < v.size(); ++i )
            out.push_back( types.index( getType( v[i] )->name ) );
        return out;
    }

    void parseTypes( Stringreader & f ) {
        if ( !typed ) {
            std::cout << "Requirement :typing needed to define types\n";
            exit( 1 );
        }

//      if this makes it in, probably need to define new subclass of Type
//      if ( costs ) insert( new Type( "NUMBER" ), tmap, types );

        // Parse the typed list
        TokenStruct< std::string > ts = f.parseTypedList( false );

        // bit of a hack to avoid object being the supertype
        if ( ts.index( "object" ) >= 0 ) {
            types[0]->name = "supertype";
            types.tokenMap.clear();
            types.tokenMap["supertype"] = 0;
        }

        // Relate subtypes and supertypes
        for ( unsigned i = 0; i < ts.size(); ++i ) {
            if (std::find(types.types.begin(), types.types.end(), ts.types[i]) == types.types.end()) {

                if ( ts.types[i].size() )
                    getType( ts.types[i] )->insertSubtype( getType( ts[i] ) );
                else getType( ts[i] );
            }
        }

        // By default, the supertype of a type is "object"
        for ( unsigned i = 1; i < types.size(); ++i )
            if ( types[i]->supertype == 0 )
                types[0]->insertSubtype( types[i] );

        for ( unsigned i = 0; DOMAIN_DEBUG && i < types.size(); ++i )
            std::cout << "  " << types[i];
    }

    void parseConstants( Stringreader & f ) {
        if ( typed && !types.size() ) {
            std::cout << "Types needed before defining constants\n";
            exit( 1 );
        }

        cons = true;

        TokenStruct< std::string > ts = f.parseTypedList( true, types );

        for ( unsigned i = 0; i < ts.size(); ++i )
            getType( ts.types[i] )->constants.insert( ts[i] );

        for ( unsigned i = 0; DOMAIN_DEBUG && i < types.size(); ++i ) {
            std::cout << " ";
            if ( typed ) std::cout << " " << types[i] << ":";
            for ( unsigned j = 0; j < types[i]->constants.size(); ++j )
                std::cout << " " << types[i]->constants[j];
            std::cout << "\n";
        }
    }

    void parsePredicates( Stringreader & f ) {
        if ( typed && !types.size() ) {
            std::cout << "Types needed before defining predicates\n";
            exit(1);
        }

        for ( f.next(); f.getChar() != ')'; f.next() ) {
            f.assert_token( "(" );
            if ( f.getChar() == ':' ) {
                // Needed to support MA-PDDL
                f.assert_token( ":private" );
                f.parseTypedList( true, types, "(" );

                // CURRENT HACK: TOTALLY IGNORE PRIVATE !!!
                --f.c;
                parsePredicates( f );
            }
            else {
                Lifted * c = new Lifted( f.getToken() );
                c->parse( f, types[0]->constants, *this );

                if ( DOMAIN_DEBUG ) std::cout << "  " << c;
                preds.insert( c );
            }
        }
        ++f.c;
    }

    void parseFunctions( Stringreader & f ) {
        if ( typed && !types.size() ) {
            std::cout << "Types needed before defining functions\n";
            exit(1);
        }

        for ( f.next(); f.getChar() != ')'; f.next() ) {
            f.assert_token( "(" );
            Function * c = new Function( f.getToken() );
            c->parse( f, types[0]->constants, *this );

            if ( DOMAIN_DEBUG ) std::cout << "  " << c;
            funcs.insert( c );
        }
        ++f.c;
    }

    virtual void parseAction( Stringreader & f ) {
        if ( !preds.size() ) {
            std::cout << "Predicates needed before defining actions\n";
            exit(1);
        }

        f.next();
        Action * a = new Action( f.getToken() );
        a->parse( f, types[0]->constants, *this );

        if ( DOMAIN_DEBUG ) std::cout << a << "\n";
        actions.insert( a );
    }

    void parseDerived( Stringreader & f ) {
        if ( !preds.size() ) {
            std::cout << "Predicates needed before defining derived predicates\n";
            exit(1);
        }

        f.next();
        Derived * d = new Derived;
        d->parse( f, types[0]->constants, *this );

        if ( DOMAIN_DEBUG ) std::cout << d << "\n";
        derived.insert( d );
    }

    void parseDurativeAction( Stringreader & f ) {
        if ( !preds.size() ) {
            std::cout << "Predicates needed before defining actions\n";
            exit(1);
        }

        f.next();
        Action * a = new TemporalAction( f.getToken() );
        a->parse( f, types[0]->constants, *this );

        if ( DOMAIN_DEBUG ) std::cout << a << "\n";
        actions.insert( a );
    }


    // Return a copy of the type structure, with newly allocated types
    // This will also copy all constants and objects!
    TokenStruct< Type * > copyTypes() {
        TokenStruct< Type * > out;
        for ( unsigned i = 0; i < types.size(); ++i )
            out.insert( types[i]->copy() );

        for ( unsigned i = 1; i < types.size(); ++i ) {
            if ( types[i]->supertype )
                out[out.index( types[i]->supertype->name )]->insertSubtype( out[i] );
            else
                out[i]->copySubtypes( types[i], out );
        }

        return out;
    }

    // Set the types to "otherTypes"
    void setTypes( const TokenStruct< Type * > & otherTypes ) {
        for ( unsigned i = 0; i < types.size(); ++i )
            delete types[i];
        types = otherTypes;
    }

    // Create a type with a given supertype (default is "object")
    void createType( const std::string & name, const std::string & parent = "object" ) {
        Type * type = new Type( name );
        types.insert( type );
        types.get( parent )->insertSubtype( type );
    }

    // Create a constant of a given type
    void createConstant( const std::string & name, const std::string & type ) {
        types.get( type )->constants.insert( name );
    }

    // Create a predicate with the given name and parameter types
    Lifted * createPredicate( const std::string & name, const StringVec & params = StringVec() ) {
        Lifted * pred = new Lifted( name );
        for ( unsigned i = 0; i < params.size(); ++i )
            pred->params.push_back( types.index( params[i] ) );
        preds.insert( pred );
        return pred;
    }

    // Create a function with the given name and parameter types
    Lifted * createFunction( const std::string & name, int type, const StringVec & params = StringVec() ) {
        Function * func = new Function( name, type );
        for ( unsigned i = 0; i < params.size(); ++i )
            func->params.push_back( types.index( params[i] ) );
        funcs.insert( func );
        return func;
    }

    // Create an action with the given name and parameter types
    Action * createAction( const std::string & name, const StringVec & params = StringVec() ) {
        Action * action = new Action( name );
        for ( unsigned i = 0; i < params.size(); ++i )
            action->params.push_back( types.index( params[i] ) );
        action->pre = new And;
        action->eff = new And;
        actions.insert( action );
        return action;
    }

    // Set the precondition of an action to "cond", converting to "And"
    void setPre( const std::string & act, Condition * cond ) {
        Action * action = actions.get( act );

        And * old = dynamic_cast< And * >( cond );
        if ( old == 0 ) {
            action->pre = new And;
            if ( cond ) dynamic_cast< And * >( action->pre )->add( cond->copy( *this ) );
        }
        else action->pre = old->copy( *this );
    }

    // Add a precondition to the action with name "act"
    void addPre( bool neg, const std::string & act, const std::string & pred, const IntVec & params = IntVec() ) {
        Action * action = actions.get( act );
        if ( action->pre == 0 ) action->pre = new And;
        And * a = dynamic_cast< And * >( action->pre );
        if ( neg ) a->add( new Not( ground( pred, params ) ) );
        else a->add( ground( pred, params ) );
    }

    // Add an "or" precondition to the action with name "act"
    void addOrPre( const std::string & act, const std::string & pred1, const std::string & pred2,
                   const IntVec & params1 = IntVec(), const IntVec & params2 = IntVec() ) {
        Or * o = new Or;
        o->first = ground( pred1, params1 );
        o->second = ground( pred2, params2 );
        Action * action = actions.get( act );
        And * a = dynamic_cast< And * >( action->pre );
        a->add( o );
    }

    // Set the precondition of an action to "cond", converting to "And"
    void setEff( const std::string & act, Condition * cond ) {
        Action * action = actions.get( act );

        And * old = dynamic_cast< And * >( cond );
        if ( old == 0 ) {
            action->eff = new And;
            if ( cond ) dynamic_cast< And * >( action->eff )->add( cond->copy( *this ) );
        }
        else action->eff = old->copy( *this );
    }

    // Add an effect to the action with name "act"
    void addEff( bool neg, const std::string & act, const std::string & pred, const IntVec & params = IntVec() ) {
        Action * action = actions.get( act );
        if ( action->eff == 0 ) action->eff = new And;
        And * a = dynamic_cast< And * >( action->eff );
        if ( neg ) a->add( new Not( ground( pred, params ) ) );
        else a->add( ground( pred, params ) );
    }

    // Add a cost to the action with name "act", in the form of an integer
    void addCost( const std::string & act, int cost ) {
        Action * action = actions.get( act );
        if ( action->eff == 0 ) action->eff = new And;
        And * a = dynamic_cast< And * >( action->eff );
        a->add( new Increase( cost ) );
    }

    // Add a cost to the action with name "act", in the form of a function
    void addCost( const std::string & act, const std::string & func, const IntVec & params = IntVec() ) {
        Action * action = actions.get( act );
        if ( action->eff == 0 ) action->eff = new And;
        And * a = dynamic_cast< And * >( action->eff );
        a->add( new Increase( funcs.get( func ), params ) );
    }

    void addFunctionModifier( const std::string & act, FunctionModifier * fm ) {
        Action * action = actions.get( act );
        if ( action->eff == 0 ) action->eff = new And;
        And * a = dynamic_cast< And * >( action->eff );
        a->add( fm );
    }

    // Create a ground condition with the given name
    Ground * ground( const std::string & name, const IntVec & params = IntVec() ) {
        if ( preds.index( name ) < 0 ) {
            std::cout << "Creating a ground condition " << name << params;
            std::cout << " failed since the predicate " << name << " does not exist!\n";
            std::exit( 1 );
        }
        return new Ground( preds[preds.index( name )], params );
    }

    // Return the list of type names corresponding to a parameter list
    StringVec typeList( ParamCond * c ) {
        StringVec out;
        for ( unsigned i = 0; i < c->params.size(); ++i )
            out.push_back( types[c->params[i]]->name );
        return out;
    }

    // Return the list of object names corresponding to a ground fluent
    StringVec objectList( Ground * g ) {
        StringVec out;
        for ( unsigned i = 0; i < g->params.size(); ++i )
            out.push_back( types[g->lifted->params[i]]->object( g->params[i] ).first );
        return out;
    }

    // Add parameters to an action
    void addParams( const std::string & name, const StringVec & v ) {
        actions.get( name )->addParams( convertTypes( v ) );
    }

    // Assert that one type is a subtype of another
    bool assertSubtype( int t1, int t2 ) {
        for ( Type * type = types[t1]; type != 0; type = type->supertype )
            if ( type->name == types[t2]->name ) return 1;
        return 0;
    }

 // Check whether the given string represents a valid constant in the model
 bool isConstant( const std::string & name) {
   bool res = false;
   for (int t = 0; t < types.size() && !res; t++) {
     for (int c = 0; c < types[t]->constants.size() && !res; c++) {
       if (types[t]->constants[c] == name) res = true;
     }
   }
   return res;
 }

 IntPair constantTypeIdConstId(const std::string & name) {
   int t, c;
   bool found = false;
   for (t = 0; t < types.size() && !found; t++) {
     for (c = 0; c < types[t]->constants.size() && !found; c++) {
       if (name == types[t]->constants[c]) found = true;
     }
   }
   if (!found) return IntPair(-1,-1);
   return IntPair(c-1,t-1);
 }

 // return the index of a constant for a given type
    int constantIndex( const std::string & name, const std::string & type ) {
        return types.get( type )->parseConstant( name ).second;
    }

    friend std::ostream& operator<<(std::ostream &os, const Domain& o) { return o.print(os); }
    virtual std::ostream& print(std::ostream& os) const {
        os << "( define ( domain " << name << " )\n";
        print_requirements(os);

        if ( typed ) {
            os << "( :types\n";
            for ( unsigned i = 1; i < types.size(); ++i )
                types[i]->PDDLPrint( os );
            os << ")\n";
        }

        if ( cons ) {
            os << "( :constants\n";
            for ( unsigned i = 0; i < types.size(); ++i )
                if ( types[i]->constants.size() ) {
                    os << "\t";
                    for ( unsigned j = 0; j < types[i]->constants.size(); ++j )
                        os << types[i]->constants[j] << " ";
                    if ( typed )
                        os << "- " << types[i]->name;
                    os << "\n";
                }
            os << ")\n";
        }

        os << "( :predicates\n";
        for ( unsigned i = 0; i < preds.size(); ++i ) {
            preds[i]->PDDLPrint( os, 1, TokenStruct< std::string >(), *this );
            os << "\n";
        }
        os << ")\n";

        if ( funcs.size() ) {
            os << "( :functions\n";
            for ( unsigned i = 0; i < funcs.size(); ++i ) {
                funcs[i]->PDDLPrint( os, 1, TokenStruct< std::string >(), *this );
                os << "\n";
            }
            os << ")\n";
        }

        for ( unsigned i = 0; i < actions.size(); ++i )
            actions[i]->PDDLPrint( os, 0, TokenStruct< std::string >(), *this );

        for ( unsigned i = 0; i < derived.size(); ++i )
            derived[i]->PDDLPrint( os, 0, TokenStruct< std::string >(), *this );

        print_addtional_blocks(os);

        os << ")\n";
        return os;
    }

    virtual std::ostream& print_requirements(std::ostream& os) const {
        os << "( :requirements";
        if ( equality ) os << " :equality";
        if ( strips ) os << " :strips";
        if ( costs ) os << " :action-cost";
        if ( adl ) os << " :adl";
        if ( neg ) os << " :negative-preconditions";
        if ( condeffects ) os << " :conditional-effects";
        if ( typed ) os << " :typing";
        if ( temp ) os << " :durative-actions";
        if ( nondet ) os << " :non-deterministic";
        if ( universal ) os << " :universal-preconditions";
        if ( fluents ) os << " :fluents";
        if ( disj ) os << " :disjuntive-preconditions";
        if ( derivedpred ) os << " :derived-predicates";
        os << " )\n";
        return os;
    }

    virtual std::ostream& print_addtional_blocks(std::ostream& os) const { return os; }

    virtual Condition * createCondition( Stringreader & f ) {
        std::string s = f.getToken();

        if ( s == "and" ) return new And;
        if ( s == "exists" ) return new Exists;
        if ( s == "forall" ) return new Forall;
        if ( s == "assign" ) return new Assign;
        if ( s == "increase" ) return new Increase;
        if ( s == "decrease" ) return new Decrease;
        if ( s == "not" ) return new Not;
        if ( s == "oneof" ) return new Oneof;
        if ( s == "or" ) return new Or;
        if ( s == "when" ) return new When;
        if ( s == "=" || s == ">=" || s == ">" || s == "<=" || s == "<" ) return new CompositeExpression( s );

        int i = preds.index( s );
        if ( i >= 0 ) return new Ground( preds[i] );

        f.tokenExit( s );

        return 0;
    }
};

} } // namespaces