.. _program_listing_file__tmp_ws_src_ros2_planning_system_plansys2_pddl_parser_include_plansys2_pddl_parser_Instance.h: Program Listing for File Instance.h =================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/ros2_planning_system/plansys2_pddl_parser/include/plansys2_pddl_parser/Instance.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once #include "plansys2_pddl_parser/Domain.h" // #undef DOMAIN_DEBUG // #define DOMAIN_DEBUG true namespace parser { namespace pddl { class Instance { public: Domain &d; std::string name; GroundVec init; // initial state Condition * goal = nullptr; // Goal condition TokenStruct< std::string > ts; bool metric; Instance( Domain & dom ) : d( dom ), metric( false ) {} Instance( Domain & dom, const std::string & s ) : Instance(dom) { parse(s); } virtual ~Instance() { for ( unsigned i = 0; i < init.size(); ++i ) delete init[i]; if (nullptr != goal) delete goal; } void parse( const std::string &s) { Stringreader f( s ); name = f.parseName( "problem" ); 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 ( t == "domain" ) parseDomain( f ); else if ( t == "objects" ) parseObjects( f ); else if ( t == "init" ) parseInit( f ); else if ( t == "goal" ) parseGoal( f ); else if ( t == "metric" ) parseMetric( f ); else f.tokenExit( t ); } } std::string getDomainName( const std::string &s) { std::string domain_name = ""; Stringreader f( s ); f.parseName( "problem" ); for ( ; f.getChar() != ')'; f.next() ) { f.assert_token( "(" ); f.assert_token( ":" ); std::string t = f.getToken(); if ( t == "domain" ) { f.next(); domain_name = f.getToken(); break; } } return domain_name; } void parseDomain( Stringreader & f ) { f.next(); f.assert_token( d.name ); f.assert_token( ")" ); } void parseObjects( Stringreader & f ) { // TokenStruct< std::string > ts = f.parseTypedList( true, d.types ); // We need to populate the global ts with the objects read from the // object construct to ensure a correct reading in other places of // the code. ts = f.parseTypedList( true, d.types ); for ( unsigned i = 0; i < ts.size(); ++i ) { Type * type = d.getType( ts.types[i] ); std::pair< bool, unsigned > pair = type->parseObject( ts[i] ); if ( pair.first == false ) type->objects.insert( ts[i] ); } for ( unsigned i = 0; DOMAIN_DEBUG && i < d.types.size(); ++i ) { std::cout << " "; if ( d.typed ) std::cout << " " << d.types[i] << ":"; for ( unsigned j = 0; j < d.types[i]->objects.size(); ++j ) std::cout << " " << d.types[i]->objects[j]; std::cout << "\n"; } } virtual void parseGround( Stringreader & f, GroundVec & v ) { TypeGround * c = 0; if ( f.getChar() == '=') { f.assert_token( "=" ); f.assert_token( "(" ); std::string s = f.getToken(); int i = d.funcs.index( s ); if ( i < 0 ) f.tokenExit( s ); if ( d.funcs[i]->returnType < 0 ) c = new GroundFunc< double >( d.funcs[i] ); else c = new GroundFunc< int >( d.funcs[i] ); } else c = new TypeGround( d.preds.get( f.getToken( d.preds ) ) ); c->parse( f, d.types[0]->constants, d ); v.push_back( c ); } void parseInit( Stringreader & f ) { for ( f.next(); f.getChar() != ')'; f.next() ) { f.assert_token( "(" ); parseGround( f, init ); } ++f.c; for ( unsigned i = 0; DOMAIN_DEBUG && i < init.size(); ++i ) std::cout << " " << init[i]; } virtual void parseGoal( Stringreader & f ) { f.next(); f.assert_token( "(" ); if ( f.getChar() != ')' ) { goal = d.createCondition( f ); goal->parse( f, ts, d ); } f.next(); f.assert_token( ")" ); } // for the moment only parse total-cost/total-time void parseMetric( Stringreader & f ) { if ( !d.temp && !d.costs ) { std::cerr << "metric only defined for temporal actions or actions with costs!\n"; std::exit( 1 ); } metric = true; f.next(); f.assert_token( "minimize" ); f.assert_token( "(" ); if ( d.temp ) f.assert_token( "total-time" ); else f.assert_token( "total-cost" ); f.assert_token( ")" ); f.assert_token( ")" ); } // add an object of a certain type void addObject( const std::string & name, const std::string & type ) { // It is not enough to insert the name as an object of the given // type. We need also to populate the TS, by insering the object // into the ts with the below two instructions to then inform // further calls to the parser, that there are the objects of the // given type. ts.insert(name); ts.types.insert(ts.types.end(), ts.size(), type); d.getType( type )->objects.insert( name ); } // add a predicate fluent to the initial state void addInit( const std::string & name, const StringVec & v = StringVec() ) { TypeGround * tg = new TypeGround( d.preds.get( name ) ); tg->insert( d, v ); init.push_back( tg ); } // add a function value to the initial state void addInit( const std::string & name, int value, const StringVec & v = StringVec() ) { GroundFunc< int > * gf = new GroundFunc< int >( d.funcs.get( name ), value ); gf->insert( d, v ); init.push_back( gf ); } // add a function value to the initial state void addInit( const std::string & name, double value, const StringVec & v = StringVec() ) { GroundFunc< double > * gf = new GroundFunc< double >( d.funcs.get( name ), value ); gf->insert( d, v ); init.push_back( gf ); } // add a fluent (predicate or function) to the initial state void addInit( TypeGround * g, const StringVec & v = StringVec() ) { TypeGround * tg = 0; GroundFunc< int > * f1 = dynamic_cast< GroundFunc< int > * >( g ); GroundFunc< double > * f2 = dynamic_cast< GroundFunc< double > * >( g ); if ( f1 ) tg = new GroundFunc< int >( d.funcs.get( g->name ), f1->value ); else if ( f2 ) tg = new GroundFunc< double >( d.funcs.get( g->name ), f2->value ); else tg = new TypeGround( d.preds.get( g->name ) ); tg->insert( d, v ); init.push_back( tg ); } // Add the goal represented by s to the Instance void addGoal(const std::string & s) { // In order to invoke the parseGoal, the input string shall also // contain an ")" for simulating the right parenthesis of "(goal // ....)", and an additional left ")" parenthesis for the part // outside. We need to handle also the empty goal case // // Alternatively, one can define another parseGoal function // that does not require these two additional characters. std::string ss = ""; if (0 == s.length()) { ss = "(and ) ))"; } else { ss = s + "))"; } Stringreader f( ss ); parseGoal( f ); } friend std::ostream& operator<<(std::ostream &os, const Instance& o) { return o.print(os); } virtual std::ostream& print(std::ostream& stream) const { stream << "( define ( problem " << name << " )\n"; stream << "( :domain " << d.name << " )\n"; stream << "( :objects\n"; for ( unsigned i = 0; i < d.types.size(); ++i ) if ( d.types[i]->objects.size() ) { stream << "\t"; for ( unsigned j = 0; j < d.types[i]->objects.size(); ++j ) stream << d.types[i]->objects[j] << " "; if ( d.typed ) stream << "- " << d.types[i]->name; stream << "\n"; } stream << ")\n"; stream << "( :init\n"; for ( unsigned i = 0; i < init.size(); ++i ) { ((TypeGround*)init[i])->PDDLPrint( stream, 1, TokenStruct< std::string >(), d ); stream << "\n"; } stream << ")\n"; stream << "( :goal\n"; if (nullptr != goal) goal->PDDLPrint(stream, 1, ts /* TokenStruct< std::string >() */, d); stream << ")\n"; if ( metric ) { stream << "( :metric minimize ( total-"; if ( d.temp ) stream << "time"; else stream << "cost"; stream << " ) )\n"; } stream << ")\n"; return stream; } }; } } // namespaces