/** Procedure for testing PeTe without Qt dependencies */ int test(int argc, char* argv[]){ bool genRandState = false; bool listformulas = false; string queryname, strategy, filename, queryString; for(int i = 1; i < argc; i++){ if(strcmp(argv[i], "--query") == 0){ queryname = argv[++i]; }else if(strcmp(argv[i], "--strategies") == 0){ std::vector<std::string> strats = ReachabilitySearchStrategy::listStrategies(); for(size_t i = 0; i < strats.size(); i++) printf("%s\n",strats[i].c_str()); }else if(strcmp(argv[i], "--literal-query") == 0){ queryString = argv[++i]; }else if(strcmp(argv[i],"--strategy") == 0){ strategy = argv[++i]; }else if(strcmp(argv[i], "--list-queries") == 0){ listformulas = true; } else if(strcmp(argv[i],"--gen-query") == 0){ genRandState = true; } else if(strcmp(argv[i],"--help") == 0){ printf("Usage: pete [net] [--query <query>] [--query-sumo <query>] [--help] [--strategies] [--strategy <strategy>]\n"); } else filename = argv[i]; } PetriNet* net = NULL; MarkVal* m0 = NULL; VarVal* v0 = NULL; std::vector<PNMLParser::Query> queries; { //Load the model ifstream modelfile(filename, ifstream::in); if(!modelfile){ fprintf(stderr, "Argument Error: Model file \"%s\" couldn't be opened\n", filename.c_str()); return ErrorCode; } //Read everything stringstream buffer; buffer << modelfile.rdbuf(); //Parse and build the petri net PetriNetBuilder builder(false); PNMLParser parser; parser.parse(buffer.str(), &builder); parser.makePetriNet(); //Build the petri net net = builder.makePetriNet(); m0 = builder.makeInitialMarking(); v0 = builder.makeInitialAssignment(); queries = parser.getQueries(); // Close the file modelfile.close(); } // List queries in file if(listformulas){ for(std::vector<PNMLParser::Query>::iterator it = queries.begin(); it != queries.end(); it++) printf("%s\n",(*it).name.c_str()); return 0; } // If generate random state if(genRandState){ //RandomDFS dfs; //dfs.reachable(*net, m0, v0, NULL); RandomQueryGenerator rng; cout<<rng.gen(*net, m0, v0)<<"\n"; return 0; } // Find the query if(queryString.empty()){ for(std::vector<PNMLParser::Query>::iterator it = queries.begin(); it != queries.end(); it++){ if((*it).name == queryname){ queryString = (*it).text; break; } } } // Parse query and analyze PQL::Condition* query = PQL::ParseQuery(queryString); AnalysisContext context(*net); query->analyze(context); //Load up reachability engine ReachabilitySearchStrategy* strat; strat = ReachabilitySearchStrategy::createStrategy(strategy); ReachabilityResult result; clock_t startClock = clock(); result = strat->reachable(*net, m0, v0, query); float finishTime = ((float)(clock() - startClock)) / (float)CLOCKS_PER_SEC; delete query; query = NULL; delete strat; strat = NULL; // Trim file name incase of alternate folder string name; bool chop = false; int index = 0; for(int i = 0; i < filename.size(); i++){ if(filename.at(i) == '/'){ chop = true; index = i; } } if(chop) name = filename.substr(index+1,filename.length()-1); delete query; query = NULL; delete strat; strat = NULL; //Print result std::string r; if(result.result() == ReachabilityResult::Satisfied) r = "Satisfied"; else if(result.result() == ReachabilityResult::NotSatisfied) r = "Not satisfiable"; else{ r = "Unknown"; } std::cout<<name <<",\t"<<queryname <<",\t"<<strategy <<",\t"<<r <<",\t"<<finishTime <<",\t"<<result.expandedStates() <<",\t"<<result.exploredStates() <<",\t"<<result.pathLength() <<std::endl; return result.result() == ReachabilityResult::Satisfied ? 0 : 1; }
bool ValidationBuilder::validate(){ //Check for duplicate identifiers set<string> reportedDuplicates; //Use a set to avoid reporting them more than once //Check variable names for(size_t i = 0; i < _varNames.size(); i++){ const string& id = _varNames[i]; int count = countMatchingIds(id); assert(count >= 1); if(count > 1 && reportedDuplicates.count(id) == 0){ reportedDuplicates.insert(id); _errors.push_back(ValidationError(id, "The identifiers must be unique, \"" + id + "\" is shared by " + int2string(count) + " entities")); } } //Check bool variable names for(size_t i = 0; i < _boolVarNames.size(); i++){ const string& id = _boolVarNames[i]; int count = countMatchingIds(id); assert(count >= 1); if(count > 1 && reportedDuplicates.count(id) == 0){ reportedDuplicates.insert(id); _errors.push_back(ValidationError(id, "The identifiers must be unique, \"" + id + "\" is shared by " + int2string(count) + " entities")); } } //Check place names for(size_t i = 0; i < _placeNames.size(); i++){ const string& id = _placeNames[i]; int count = countMatchingIds(id); assert(count >= 1); if(count > 1 && reportedDuplicates.count(id) == 0){ reportedDuplicates.insert(id); _errors.push_back(ValidationError(id, "The identifiers must be unique, \"" + id + "\" is shared by " + int2string(count) + " entities")); } } //Check transition names for(size_t i = 0; i < _transitionNames.size(); i++){ const string& id = _transitionNames[i]; int count = countMatchingIds(id); assert(count >= 1); if(count > 1 && reportedDuplicates.count(id) == 0){ reportedDuplicates.insert(id); _errors.push_back(ValidationError(id, "The identifiers must be unique, \"" + id + "\" is shared by " + int2string(count) + " entities")); } } //Check all input arcs for(size_t i = 0; i < _inputArcs.size(); i++){ const Arc& arc = _inputArcs[i]; bool foundPlace = false; bool foundTransition = false; //Look for place for(size_t j = 0; j < _placeNames.size(); j++){ foundPlace |= _placeNames[j] == arc.start; if(foundPlace) break; } //Look for transition for(size_t j = 0; j < _transitionNames.size(); j++){ foundTransition |= _transitionNames[j] == arc.end; if(foundTransition) break; } //Report error if(!foundPlace || !foundTransition){ string msg; if(!foundPlace && !foundTransition) msg = "Neigther end-points found"; else if(!foundPlace) msg = "Start-place \"" + arc.start + "\" not found"; else msg = "End-transition \"" + arc.end + "\" not found"; _errors.push_back(ValidationError(arc.start, arc.end, msg)); } } //Check all output arcs for(size_t i = 0; i < _outputArcs.size(); i++){ const Arc& arc = _outputArcs[i]; bool foundPlace = false; bool foundTransition = false; //Look for transition for(size_t j = 0; j < _transitionNames.size(); j++){ foundTransition |= _transitionNames[j] == arc.start; if(foundTransition) break; } //Look for place for(size_t j = 0; j < _placeNames.size(); j++){ foundPlace |= _placeNames[j] == arc.end; if(foundPlace) break; } //Report error if(!foundPlace || !foundTransition){ string msg; if(!foundPlace && !foundTransition) msg = "Neither end-points found"; else if(!foundPlace) msg = "End-place \"" + arc.end + "\" not found"; else msg = "Start-transition \"" + arc.start + "\" not found"; _errors.push_back(ValidationError(arc.start, arc.end, msg)); } } //Attempt to parse all non-empty conditions for(size_t i = 0; i < _conditions.size(); i++){ if(_conditions[i].empty()) continue; //PQL::Condition* cond = PQL::ParseQuery(_conditions[i]); PQL::Condition* cond = PQL::ParseCondition(_conditions[i]); if(cond){ PQL::AnalysisContext context(_placeNames, _varNames, _boolVarNames); cond->analyze(context); for(size_t j = 0; j < context.errors().size(); j++){ _errors.push_back(ValidationError(_transitionNames[i], context.errors()[j], true)); } delete cond; cond = NULL; }else _errors.push_back(ValidationError(_transitionNames[i], "Unable to parse non-empty condition")); } //Attempt to parse all non-empty assignments for(size_t i = 0; i < _assignments.size(); i++){ if(_assignments[i].empty()) continue; //PQL::AssignmentExpression* a = PQL::ParseAssignment(_assignments[i]); PQL::AssignmentExpression* a = PQL::ParseConditionAssignment(_assignments[i]); if(a){ PQL::AnalysisContext context(_placeNames, _varNames, _boolVarNames); a->analyze(context); for(size_t j = 0; j < context.errors().size(); j++){ _errors.push_back(ValidationError(_transitionNames[i], context.errors()[j], false)); } delete a; a = NULL; }else _errors.push_back(ValidationError(_transitionNames[i], "Unable to parse non-empty assignment")); } return _errors.empty(); }