/** * Constructor. * @param graph The automaton (NBA) that contains this state. */ public NBA_State(NBA graph, int index) { _graph = graph; _isFinal = false; _edge_manager = new NBA_State_EdgeManager(this, graph.getAPSet()); Index = index; }
/** * Convert an LTL formula to a DRA. * @param ltl the LTL formula * @param options which operators are allowed * @return a shared_ptr to the DRA */ private DRA ltl2dra(LTLFormula ltl, BuchiAutomata buchiAutomata, LTL2DSTAR_Options options) { APSet ap_set = ltl.getAPSet(); LTLFormula ltl_pnf = ltl.toPNF(); if (options.allow_union && ltl_pnf.getRootNode().getType() == type_t.T_OR) { LTLFormula ltl_left = ltl_pnf.getSubFormula(ltl_pnf.getRootNode().getLeft()); LTLFormula ltl_right = ltl_pnf.getSubFormula(ltl_pnf.getRootNode().getRight()); LTL2DSTAR_Options rec_opt = options; rec_opt.recursion(); DRA dra_left = ltl2dra(ltl_left, buchiAutomata, rec_opt); DRA dra_right = ltl2dra(ltl_right, buchiAutomata, rec_opt); return(DRA.calculateUnion(dra_left, dra_right, _safra_opt.union_trueloop) as DRA); } if (options.safety) { LTLSafetyAutomata lsa = new LTLSafetyAutomata(); DRA safety_dra = lsa.ltl2dra(ltl, buchiAutomata); if (safety_dra != null) { return(safety_dra); } } DRA dra = new DRA(ap_set); NBA nba = LTL2NBA.ltl2nba(ltl_pnf, buchiAutomata); if (nba == null) { throw new Exception("Couldn't create NBA from LTL formula"); } NBA2DRA nba2dra = new NBA2DRA(_safra_opt); nba2dra.convert(nba, dra); if (options.optimizeAcceptance) { dra.optimizeAcceptanceCondition(); } if (options.bisim) { DRAOptimizations dra_optimizer = new DRAOptimizations(); dra = dra_optimizer.optimizeBisimulation(dra); } return(dra); }
/** * Convert the NBA to a DRA using Safra's algorithm, using stuttering * @param nba the NBA * @param dra_result the result DRA * @param limit limit for the size of the DRA */ //template < typename NBA_t, typename DRA_t > void convert_safra_stuttered(NBA nba, DRA dra_result, int limit) //=0 { SafraAlgorithm safras_algo = new SafraAlgorithm(nba, _options); StutteredNBA2DA nba2dra_stuttered = new StutteredNBA2DA(_detailed_states, _stutter_information); nba2dra_stuttered.convert(safras_algo, dra_result, limit); }
public static DRA dba2dra(NBA nba, bool complement) { APSet ap_set = nba.getAPSet(); ; DRA dra_p = new DRA(ap_set); dba2dra(nba, dra_p, complement); return dra_p; }
public static DRA dba2dra(NBA nba, bool complement) { APSet ap_set = nba.getAPSet();; DRA dra_p = new DRA(ap_set); dba2dra(nba, dra_p, complement); return(dra_p); }
/** Check for partial stutter insensitiveness using * the nba and the complement nba */ public void checkNBAs(NBA nba, NBA nba_complement) { APSet apset = nba.getAPSet_cp(); bool nba_is_smaller = (nba.size() < nba_complement.size()); //if (_printInfo) { // std::cerr << "Checking for insensitiveness" << std::endl; //} bool one_insensitive = false; bool all_insensitive = true; //for (APSet::element_iterator it=apset->all_elements_begin(); it!=apset->all_elements_end();++it) for (int it = apset.all_elements_begin(); it != apset.all_elements_end(); ++it) { APElement elem = new APElement(it); if (_partiallyInsensitive.get(it)) { // don't recheck something we already now is stutter insensitive one_insensitive = true; continue; } // if (_printInfo) { //std::cerr << "Checking " << elem.toString(*apset) << ": "; //std::cerr.flush(); // } bool insensitive; if (nba_is_smaller) { insensitive = is_stutter_insensitive(nba, nba_complement, elem); } else { insensitive = is_stutter_insensitive(nba_complement, nba, elem); } if (insensitive) { _partiallyInsensitive.set(it); one_insensitive = true; //if (_printInfo) { // std::cerr << "+" << std::endl; //} } else { all_insensitive = false; //if (_printInfo) { // std::cerr << "-" << std::endl; //} } } _hasCheckedNBAs = true; _partiallyStutterInsensitive = one_insensitive; }
/** * Generate a DRA for an LTL formula using scheck * @param ltl the formula * @param scheck_path the path to the scheck executable * @return a shared_ptr to the generated DRA (on failure returns a ptr to 0) */ //template <class DRA> //typename DRA::shared_ptr public DRA ltl2dra(LTLFormula ltl, BuchiAutomata buchiAutomata) { LTLFormula ltl_; LTLFormula ltl_for_scheck = null; bool safe = false; if (ltl.isSafe()) { safe = true; ltl_ = ltl.negate(); ltl_for_scheck = ltl_; } else if (ltl.isCoSafe()) { ltl_for_scheck = ltl; } else { if (_only_syn) { // Not syntactically safe -> abort //typename //DRA::shared_ptr p; //return p; return(null); } } // std::cerr<< "Calling scheck with " // <<ltl_for_scheck->toStringPrefix() << " : " << safe << std::endl; //NBA nba = ltl2dba(ltl_for_scheck, buchiAutomata); //, scheck_path, _only_syn NBA nba = LTL2NBA.ltl2nba(ltl_for_scheck, buchiAutomata); //, scheck_path, _only_syn if (nba == null) { //typename //DRA::shared_ptr p; //return p; return(null); } // nba->print(std::cerr); // safe -> negate DRA return(DBA2DRA.dba2dra(nba, safe)); // return dba2dra<DRA>(*nba, safe); // nba is auto-destructed //<NBA_t,DRA> }
public NBA ltl2nba(LTLFormula ltl, BuchiAutomata buchiAutomata, bool exception_on_failure) { //Debug.Assert(_ltl2nba != null); NBA nba = LTL2NBA.ltl2nba(ltl, buchiAutomata); if (exception_on_failure && nba == null) { throw new Exception("Couldn't generate NBA from LTL formula!"); } return(nba); }
// -- private member functions /** Check that symbol label is stutter insensitive, * using nba and complement_nba */ public bool is_stutter_insensitive(NBA nba, NBA nba_complement, APElement label) { NBA stutter_closed_nba = NBAStutterClosure.stutter_closure(nba, label); NBA product = NBA.product_automaton(stutter_closed_nba, nba_complement); NBAAnalysis analysis_product = new NBAAnalysis(product); bool empty = analysis_product.emptinessCheck(); // std::cerr << "NBA is " << (empty ? "empty" : "not empty") << std::endl; return(empty); }
/** Constructor */ public SCC_DFS(NBA graph, SCCs result, APElement label) // { _graph = graph; _result = result; //_successor_access = successor_access; _labelMark = label; /** The DFS stack */ _stack = new Stack <int>(); /** The SCC_DFS_Data for every state (state index -> DFS_DATA) */ _dfs_data = new List <SCC_DFS_Data>(); }
public void convert(NBA nba, DRA dra_result, int limit) //=0 { if (nba.size() == 0 || nba.getStartState() == null) { // the NBA is empty -> construct DRA that is empty dra_result.constructEmpty(); return; } if (_options.dba_check && nba.isDeterministic()) { DBA2DRA.dba2dra(nba, dra_result); return; } if (_options.stutter_closure) { if (_stutter_information != null && !_stutter_information.isCompletelyInsensitive()) { //std::cerr << //"WARNING: NBA might not be 100% stutter insensitive, applying stutter closure can create invalid results!" << //std::endl; } NBA nba_closed = NBAStutterClosure.stutter_closure(nba); if (can_stutter()) { convert_safra_stuttered(nba_closed, dra_result, limit); return; } convert_safra(nba_closed, dra_result, limit); return; } if (can_stutter()) { convert_safra_stuttered(nba, dra_result, limit); return; } convert_safra(nba, dra_result, limit); return; }
/** * Convert an NBA to a DRA using Safra's algorithm. * If limit is specified (>0), the conversion is * aborted with LimitReachedException when the number of * states exceeds the limit. * @param nba the formula * @param limit a limit on the number of states (0 for no limit) * @param detailedStates save detailed interal information (Safra trees) * in the generated states * @param stutter_information Information about the symbols that can be stuttered * @return a shared_ptr to the created DRA */ public DRA nba2dra(NBA nba, int limit, bool detailedStates, StutterSensitivenessInformation stutter_information) { DRA dra = new DRA(nba.getAPSet_cp()); NBA2DRA nba2dra = new NBA2DRA(_safra_opt, detailedStates, stutter_information); try { nba2dra.convert(nba, dra, limit); } catch (LimitReachedException e) { //dra.reset(); // rethrow to notify caller //throw; } return dra; }
/** * Convert an NBA to a DRA using Safra's algorithm. * If limit is specified (>0), the conversion is * aborted with LimitReachedException when the number of * states exceeds the limit. * @param nba the formula * @param limit a limit on the number of states (0 for no limit) * @param detailedStates save detailed interal information (Safra trees) * in the generated states * @param stutter_information Information about the symbols that can be stuttered * @return a shared_ptr to the created DRA */ public DRA nba2dra(NBA nba, int limit, bool detailedStates, StutterSensitivenessInformation stutter_information) { DRA dra = new DRA(nba.getAPSet_cp()); NBA2DRA nba2dra = new NBA2DRA(_safra_opt, detailedStates, stutter_information); try { nba2dra.convert(nba, dra, limit); } catch (LimitReachedException e) { //dra.reset(); // rethrow to notify caller //throw; } return(dra); }
/** * Convert the NBA to a DRA using Safra's algorithm * @param nba the NBA * @param dra_result the result DRA * @param limit limit for the size of the DRA */ public void convert_safra(NBA nba, DRA dra_result, int limit) //=0 { SafraAlgorithm safras_algo = new SafraAlgorithm(nba, _options); if (!_options.opt_rename) { NBA2DA nba2da = new NBA2DA(_detailed_states); nba2da.convert(safras_algo, dra_result, limit); } else { //typedef typename SafrasAlgorithm<NBA_t>::result_t result_t; //typedef typename SafrasAlgorithm<NBA_t>::state_t key_t; //<safra_t,DRA_t, StateMapperFuzzy<result_t, key_t, typename DRA_t::state_type, SafraTreeCandidateMatcher> > NBA2DA nba2da_fuzzy = new NBA2DA(_detailed_states); nba2da_fuzzy.convert(safras_algo, dra_result, limit); } }
/** Calculate the SCCs for Graph graph and save in result. */ //public static void calculateSCCs(NBA graph, SCCs result) //{ // calculateSCCs(graph, result, false); //} /** Calculate the SCCs for Graph graph and save in result. */ public static void calculateSCCs(NBA graph, SCCs result, bool disjoint, APElement label) { // =false, SuccessorAccess successor_access=SuccessorAccess() SCC_DFS.calculateSCCs(graph, result, disjoint, label); //, successor_access }
/** * Internal helper function to perform the conversion from NBA to DRA. * @param nba the NBA (has to be deterministic) * @param dra_result the DRA into which the converted automaton is saved * @param complement complement the DBA? */ public static void dba2dra(NBA nba, DRA dra_result) { dba2dra(nba, dra_result, false); }
/** Calculate the stutter closure for the NBA, for a certain symbol. * @param nba the NBA * @param label the symbol for which to perform the stutter closure */ public static NBA stutter_closure(NBA nba, APElement label) { APSet apset = nba.getAPSet_cp(); NBA nba_result_ptr = new NBA(apset); NBA result = nba_result_ptr; int element_count = apset.powersetSize(); Debug.Assert(nba.getStartState() != null); int start_state = nba.getStartState().getName(); for (int i = 0; i < nba.size(); i++) { int st = result.nba_i_newState(); Debug.Assert(st == i); if (st == start_state) { result.setStartState(result[st]); } if (nba[st].isFinal()) { result[st].setFinal(true); } } for (int i = 0; i < nba.size(); i++) { int st = result.nba_i_newState(); Debug.Assert(st == nba.size() + i); result[st].addEdge(label, result[i]); result[st].addEdge(label, result[st]); } //List<BitSet> reachable = null; //NBAEdgeSuccessors edge_successor = new NBAEdgeSuccessors(label); SCCs scc = new SCCs(); GraphAlgorithms.calculateSCCs(nba, scc, true, label); //,edge_successor List <BitSet> reachable = scc.getReachabilityForAllStates(); // std::cerr << "SCCs for " << label.toString(*apset) << std::endl; // std::cerr << scc << std::endl; // std::cerr << " Reachability: "<< std::endl; // for (unsigned int t=0; t < reachable->size(); t++) { // std::cerr << t << " -> " << (*reachable)[t] << std::endl; // } // std::cerr << " ---\n"; for (int i = 0; i < nba.size(); i++) { NBA_State from = result[i]; for (int j = 0; j < element_count; j++) { BitSet result_to = new BitSet(); BitSet to = nba[i].getEdge(new APElement(j)); if (j != label.bitset) { result_to = to; } else { //for (BitSetIterator it=BitSetIterator(*to);it!=BitSetIterator::end(*to);++it) for (int it = BitSetIterator.start(to); it != BitSetIterator.end(to); it = BitSetIterator.increment(to, it)) { int to_state = it; // We can go directly to the original state result_to.set(to_state); // We can also go to the corresponding stutter state instead int stutter_state = nba.size() + to_state; result_to.set(stutter_state); // ... and then we can go directly to all the states that are j-reachable from to result_to.Union(reachable[to_state]); } } from.getEdge(new APElement(j)).Assign(result_to); } } //delete reachable; return(nba_result_ptr); }
//, SuccessorAccess& successor_access /** Calculate the SCCs for Graph graph and save in result. */ public static void calculateSCCs(NBA graph, SCCs result, bool disjoint, APElement label) { SCC_DFS scc_dfs = new SCC_DFS(graph, result, label); scc_dfs.calculate(disjoint); }
// /** Constructor */ public SCC_DFS(NBA graph, SCCs result, APElement label) { _graph = graph; _result = result; //_successor_access = successor_access; _labelMark = label; /** The DFS stack */ _stack = new Stack<int>(); /** The SCC_DFS_Data for every state (state index -> DFS_DATA) */ _dfs_data = new List<SCC_DFS_Data>(); }
/** * Convert an NBA to an DRA (having APElements as edge labels). * Throws LimitReachedException if a limit is set (>0) and * there are more states in the generated DRA than the limit. * @param nba the NBA * @param dra_result the DRA where the result is stored * (has to have same APSet as the nba) * @param limit a limit for the number of states (0 disables the limit). */ //template < typename NBA_t, typename DRA_t> public void convert(NBA nba, DRA dra_result) //=0 { convert(nba, dra_result, 0); }
/** Generate the tree */ public override void generateTree() { LTL2DSTAR_Tree_Rabin rabin = null; LTL2DSTAR_Tree_Streett streett = null; if (_options.automata == automata_type.RABIN || _options.automata == automata_type.RABIN_AND_STREETT) { rabin = new LTL2DSTAR_Tree_Rabin(_ltl, buchiAutomata, _options, _sched); } if (_options.automata == automata_type.STREETT || _options.automata == automata_type.RABIN_AND_STREETT) { streett = new LTL2DSTAR_Tree_Streett(_ltl.negate().toPNF(), buchiAutomata, _options, _sched); } if (rabin != null && streett != null) { int rabin_est = rabin.guestimate(); int streett_est = streett.guestimate(); //if (_options.verbose_scheduler) { // std::cerr << "NBA-Estimates: Rabin: "<<rabin_est << // " Streett: " << streett_est << std::endl; //} if (rabin_est <= streett_est) { addChild(rabin); addChild(streett); } else { addChild(streett); addChild(rabin); } } else { if (rabin != null) { addChild(rabin); } if (streett != null) { addChild(streett); } } if (_options.opt_safra.stutter) { StutterSensitivenessInformation stutter_information = new StutterSensitivenessInformation(); stutter_information.checkLTL(_ltl); if (!stutter_information.isCompletelyInsensitive() && _options.opt_safra.partial_stutter_check) { NBA nba = null; NBA complement_nba = null; if (rabin != null) { nba = rabin.getNBA(); } else if (streett != null) { nba = streett.getNBA(); } if (rabin != null && streett != null) { complement_nba = streett.getNBA(); } if (nba == null) { stutter_information.checkPartial(_ltl, buchiAutomata, _sched.getLTL2DRA());//////////add buchiAutomata } else if (complement_nba == null) { stutter_information.checkPartial(nba, buchiAutomata, _ltl.negate().toPNF(), _sched.getLTL2DRA());///////////add buchiAutomata } else { stutter_information.checkNBAs(nba, complement_nba); } } if (rabin != null) { rabin.setStutterInformation(stutter_information); } if (streett != null) { streett.setStutterInformation(stutter_information); } } }
/** * Convert an LTL formula to an NBA * @param ltl * @return a pointer to the created NBA (caller gets ownership). */ public static NBA ltl2nba(LTLFormula ltl, BuchiAutomata buchiAutomata) { // Create canonical APSet (with 'p0', 'p1', ... as AP) //LTLFormula ltl_canonical = ltl.copy(); //APSet canonical_apset = ltl.getAPSet().createCanonical(); // ltl_canonical.switchAPSet(canonical_apset); //AnonymousTempFile spin_outfile; //std::vector<std::string> arguments; //arguments.push_back("-f"); //arguments.push_back(ltl_canonical->toStringInfix()); //arguments.insert(arguments.end(), _arguments.begin(),_arguments.end()); //const char *program_path=_path.c_str(); //RunProgram spin(program_path, // arguments, // false, // 0, // &spin_outfile, // 0); //int rv=spin.waitForTermination(); //if (rv==0) { // NBA_t *result_nba(new NBA_t(canonical_apset)); // FILE *f=spin_outfile.getInFILEStream(); // if (f==NULL) { //throw Exception(""); // } // int rc=nba_parser_promela::parse(f, result_nba); // fclose(f); // if (rc!=0) { //throw Exception("Couldn't parse PROMELA file!"); // } NBA result_nba = new NBA(ltl.getAPSet()); //////////////////////////////////////////////////////////// //todo: create the NBA from the BA // // //////////////////////////////////////////////////////////// NBABuilder builder = new NBABuilder(result_nba); //int current_state = 0; //bool current_state_valid=false; //foreach (string state in buchiAutomata.States) //{ // if (buchiAutomata.InitialStates.Contains(state)) // { // int current_state = builder.findOrAddState(state); // if (buchiAutomata.InitialStates.Contains(state)) // { // builder.setStartState(current_state); // } // } //} foreach (string state in buchiAutomata.States) { //if (!buchiAutomata.InitialStates.Contains(state)) { ////s.AppendLine(state); //if (current_state_valid) { // builder.addAdditionalNameToState(state, current_state); //} //else //{ int current_state = builder.findOrAddState(state); //std::string& label=$1; //if (label.find("accept") != std::string::npos) { if (state.EndsWith(Constants.ACCEPT_STATE)) { builder.setFinal(current_state); } //if (label.find("accept_all") != std::string ::npos) //{ // // dirty hack: accept_all + skip -> trueloop // builder.setFinal(current_state); // builder.addEdge(current_state, current_state, std::string ("t")); //} if (buchiAutomata.InitialStates.Contains(state)) { builder.setStartState(current_state); } //current_state_valid = true; //} } } //s.AppendLine("Transitions"); foreach (Transition transition in buchiAutomata.Transitions) { int from = builder.findOrAddState(transition.FromState); int to = builder.findOrAddState(transition.ToState); builder.addEdge(from, to, transition.labels); } // switch back to original APSet //result_nba.switchAPSet(ltl.getAPSet()); //todo: //construct the NBA here return result_nba; }
// -- private member functions /** Check that symbol label is stutter insensitive, * using nba and complement_nba */ public bool is_stutter_insensitive(NBA nba, NBA nba_complement, APElement label) { NBA stutter_closed_nba = NBAStutterClosure.stutter_closure(nba, label); NBA product = NBA.product_automaton(stutter_closed_nba, nba_complement); NBAAnalysis analysis_product = new NBAAnalysis(product); bool empty = analysis_product.emptinessCheck(); // std::cerr << "NBA is " << (empty ? "empty" : "not empty") << std::endl; return empty; }
/** Check for partial stutter insensitiveness for a LTL formula, using an * already calculated NBA. * @param nba an NBA for the positive formula * @param ltl_neg the negated LTL formula (in PNF) * @param llt2nba the LTL2NBA translator, has to provide function ltl2nba(ltl) */ public void checkPartial(NBA nba, BuchiAutomata ba, LTLFormula ltl_neg, LTL2DRA ltl2nba) { checkNBAs(nba, ltl2nba.ltl2nba(ltl_neg, ba)); }
/** * Constructor. */ public STVisitor_powerset(NBA nba, APElement elem) { _nba = nba; _elem = elem; }
public static NBA product_automaton(NBA nba_1, NBA nba_2) { Debug.Assert(nba_1.getAPSet() == nba_2.getAPSet()); NBA product_nba = new NBA(nba_1.getAPSet_cp()); APSet apset = nba_1.getAPSet(); Debug.Assert(apset == nba_2.getAPSet()); for (int s_1 = 0; s_1 < nba_1.size(); s_1++) { for (int s_2 = 0; s_2 < nba_2.size(); s_2++) { for (int copy = 0; copy < 2; copy++) { int s_r = product_nba.nba_i_newState(); Debug.Assert(s_r == (s_1 * nba_2.size() + s_2) * 2 + copy); int to_copy = copy; if (copy == 0 && nba_1[s_1].isFinal()) { to_copy = 1; } if (copy == 1 && nba_2[s_2].isFinal()) { product_nba[s_r].setFinal(true); to_copy = 0; } //for (typename APSet::element_iterator it=apset.all_elements_begin();it!=apset.all_elements_end();++it) for (int it = apset.all_elements_begin(); it != apset.all_elements_end(); it++) { APElement label = new APElement(it); BitSet to_s1 = nba_1[s_1].getEdge(label); BitSet to_s2 = nba_2[s_2].getEdge(label); BitSet to_set = new BitSet(); //for (BitSetIterator it_e_1 = BitSetIterator(*to_s1); it_e_1 != BitSetIterator::end(*to_s1); ++it_e_1) //for (int it_e_1 = 0; it_e_1 != to_s1.bitset.Count; ++it_e_1) for (int it_e_1 = BitSetIterator.start(to_s1); it_e_1 != BitSetIterator.end(to_s1); it_e_1 = BitSetIterator.increment(to_s1, it_e_1)) { //for (BitSetIterator it_e_2 = BitSetIterator(*to_s2); it_e_2 != BitSetIterator::end(*to_s2); ++it_e_2) //for (int it_e_2 = 0; it_e_2 != to_s2.bitset.Count; ++it_e_2) for (int it_e_2 = BitSetIterator.start(to_s2); it_e_2 != BitSetIterator.end(to_s2); it_e_2 = BitSetIterator.increment(to_s2, it_e_2)) { int to = it_e_1 * nba_2.size() + it_e_2 * 2 + to_copy; to_set.set(to); } } product_nba[s_r].getEdge(label).Assign(to_set); } } } } int start_1 = nba_1.getStartState().getName(); int start_2 = nba_2.getStartState().getName(); product_nba.setStartState(product_nba[start_1 * nba_2.size() + start_2]); return product_nba; }
/** Calculate the stutter closure for the NBA, for a certain symbol. * @param nba the NBA * @param label the symbol for which to perform the stutter closure */ public static NBA stutter_closure(NBA nba, APElement label) { APSet apset = nba.getAPSet_cp(); NBA nba_result_ptr = new NBA(apset); NBA result = nba_result_ptr; int element_count = apset.powersetSize(); Debug.Assert(nba.getStartState() != null); int start_state = nba.getStartState().getName(); for (int i = 0; i < nba.size(); i++) { int st = result.nba_i_newState(); Debug.Assert(st == i); if (st == start_state) { result.setStartState(result[st]); } if (nba[st].isFinal()) { result[st].setFinal(true); } } for (int i = 0; i < nba.size(); i++) { int st = result.nba_i_newState(); Debug.Assert(st == nba.size() + i); result[st].addEdge(label, result[i]); result[st].addEdge(label, result[st]); } //List<BitSet> reachable = null; //NBAEdgeSuccessors edge_successor = new NBAEdgeSuccessors(label); SCCs scc = new SCCs(); GraphAlgorithms.calculateSCCs(nba, scc, true, label); //,edge_successor List<BitSet> reachable = scc.getReachabilityForAllStates(); // std::cerr << "SCCs for " << label.toString(*apset) << std::endl; // std::cerr << scc << std::endl; // std::cerr << " Reachability: "<< std::endl; // for (unsigned int t=0; t < reachable->size(); t++) { // std::cerr << t << " -> " << (*reachable)[t] << std::endl; // } // std::cerr << " ---\n"; for (int i = 0; i < nba.size(); i++) { NBA_State from = result[i]; for (int j = 0; j < element_count; j++) { BitSet result_to = new BitSet(); BitSet to = nba[i].getEdge(new APElement(j)); if (j != label.bitset) { result_to = to; } else { //for (BitSetIterator it=BitSetIterator(*to);it!=BitSetIterator::end(*to);++it) for (int it = BitSetIterator.start(to); it != BitSetIterator.end(to); it = BitSetIterator.increment(to, it)) { int to_state = it; // We can go directly to the original state result_to.set(to_state); // We can also go to the corresponding stutter state instead int stutter_state = nba.size() + to_state; result_to.set(stutter_state); // ... and then we can go directly to all the states that are j-reachable from to result_to.Union(reachable[to_state]); } } from.getEdge(new APElement(j)).Assign(result_to); } } //delete reachable; return nba_result_ptr; }
public static NBA product_automaton(NBA nba_1, NBA nba_2) { Debug.Assert(nba_1.getAPSet() == nba_2.getAPSet()); NBA product_nba = new NBA(nba_1.getAPSet_cp()); APSet apset = nba_1.getAPSet(); Debug.Assert(apset == nba_2.getAPSet()); for (int s_1 = 0; s_1 < nba_1.size(); s_1++) { for (int s_2 = 0; s_2 < nba_2.size(); s_2++) { for (int copy = 0; copy < 2; copy++) { int s_r = product_nba.nba_i_newState(); Debug.Assert(s_r == (s_1 * nba_2.size() + s_2) * 2 + copy); int to_copy = copy; if (copy == 0 && nba_1[s_1].isFinal()) { to_copy = 1; } if (copy == 1 && nba_2[s_2].isFinal()) { product_nba[s_r].setFinal(true); to_copy = 0; } //for (typename APSet::element_iterator it=apset.all_elements_begin();it!=apset.all_elements_end();++it) for (int it = apset.all_elements_begin(); it != apset.all_elements_end(); it++) { APElement label = new APElement(it); BitSet to_s1 = nba_1[s_1].getEdge(label); BitSet to_s2 = nba_2[s_2].getEdge(label); BitSet to_set = new BitSet(); //for (BitSetIterator it_e_1 = BitSetIterator(*to_s1); it_e_1 != BitSetIterator::end(*to_s1); ++it_e_1) //for (int it_e_1 = 0; it_e_1 != to_s1.bitset.Count; ++it_e_1) for (int it_e_1 = BitSetIterator.start(to_s1); it_e_1 != BitSetIterator.end(to_s1); it_e_1 = BitSetIterator.increment(to_s1, it_e_1)) { //for (BitSetIterator it_e_2 = BitSetIterator(*to_s2); it_e_2 != BitSetIterator::end(*to_s2); ++it_e_2) //for (int it_e_2 = 0; it_e_2 != to_s2.bitset.Count; ++it_e_2) for (int it_e_2 = BitSetIterator.start(to_s2); it_e_2 != BitSetIterator.end(to_s2); it_e_2 = BitSetIterator.increment(to_s2, it_e_2)) { int to = it_e_1 * nba_2.size() + it_e_2 * 2 + to_copy; to_set.set(to); } } product_nba[s_r].getEdge(label).Assign(to_set); } } } } int start_1 = nba_1.getStartState().getName(); int start_2 = nba_2.getStartState().getName(); product_nba.setStartState(product_nba[start_1 * nba_2.size() + start_2]); return(product_nba); }
//=0 /** * Convert the NBA to a DRA using Safra's algorithm * @param nba the NBA * @param dra_result the result DRA * @param limit limit for the size of the DRA */ public void convert_safra(NBA nba, DRA dra_result, int limit) { SafraAlgorithm safras_algo = new SafraAlgorithm(nba, _options); if (!_options.opt_rename) { NBA2DA nba2da = new NBA2DA(_detailed_states); nba2da.convert(safras_algo, dra_result, limit); } else { //typedef typename SafrasAlgorithm<NBA_t>::result_t result_t; //typedef typename SafrasAlgorithm<NBA_t>::state_t key_t; //<safra_t,DRA_t, StateMapperFuzzy<result_t, key_t, typename DRA_t::state_type, SafraTreeCandidateMatcher> > NBA2DA nba2da_fuzzy = new NBA2DA(_detailed_states); nba2da_fuzzy.convert(safras_algo, dra_result, limit); } }
//=0 /** * Convert an NBA to an DRA (having APElements as edge labels). * Throws LimitReachedException if a limit is set (>0) and * there are more states in the generated DRA than the limit. * @param nba the NBA * @param dra_result the DRA where the result is stored * (has to have same APSet as the nba) * @param limit a limit for the number of states (0 disables the limit). */ //template < typename NBA_t, typename DRA_t> public void convert(NBA nba, DRA dra_result) { convert(nba, dra_result, 0); }
/** Calculate the stutter closure for the NBA, for all symbols. * @param nba the NBA */ public static NBA stutter_closure(NBA nba) { APSet apset = nba.getAPSet_cp(); NBA nba_result_ptr = new NBA(apset); NBA result = nba_result_ptr; int element_count = apset.powersetSize(); Debug.Assert(nba.getStartState() != null); int start_state = nba.getStartState().getName(); for (int i = 0; i < nba.size(); i++) { int st = result.nba_i_newState(); Debug.Assert(st == i); if (st == start_state) { result.setStartState(result[st]); } if (nba[st].isFinal()) { result[st].setFinal(true); } } for (int i = 0; i < nba.size(); i++) { for (int j = 0; j < element_count; j++) { int st = result.nba_i_newState(); Debug.Assert(st == nba.size() + (i * element_count) + j); result[st].addEdge(new APElement(j), result[i]); result[st].addEdge(new APElement(j), result[st]); } } List <List <BitSet> > reachable = new List <List <BitSet> >(); //reachable.resize(element_count); Ultility.resize(reachable, element_count); for (int j = 0; j < element_count; j++) { //NBAEdgeSuccessors edge_successor = new NBAEdgeSuccessors(new APElement(j)); SCCs scc = new SCCs(); GraphAlgorithms.calculateSCCs(nba, scc, true, new APElement(j)); //,edge_successor reachable[j] = scc.getReachabilityForAllStates(); #if VERBOSE std::cerr << "SCCs for " << APElement(j).toString(*apset) << std::endl; std::cerr << scc << std::endl; std::cerr << " Reachability: " << std::endl; std::vector <BitSet>& reach = *reachable[j]; for (unsigned int t = 0; t < reach.size(); t++) { std::cerr << t << " -> " << reach[t] << std::endl; } std::cerr << " ---\n"; #endif } for (int i = 0; i < nba.size(); i++) { NBA_State from = result[i]; for (int j = 0; j < element_count; j++) { BitSet result_to = new BitSet(); BitSet to = nba[i].getEdge(new APElement(j)); //for (BitSetIterator it=BitSetIterator(*to);it!=BitSetIterator::end(*to);++it) for (int it = BitSetIterator.start(to); it != BitSetIterator.end(to); it = BitSetIterator.increment(to, it)) { int to_state = it; // We can go directly to the original state result_to.set(to_state); // We can also go to the corresponding stutter state instead int stutter_state = nba.size() + (to_state * element_count) + j; result_to.set(stutter_state); // ... and then we can go directly to all the states that are j-reachable from to result_to.Union(reachable[j][to_state]); } from.getEdge(new APElement(j)).Assign(result_to); } } //for (int i=0; i<reachable.size(); ++i) { // delete reachable[i]; // } return(nba_result_ptr); }
/** * Convert a deterministic B點hi automaton * (a nondeterministic B點hi automaton NBA, where every transition * has at most one target state) to an equivalent deterministic * Rabin automaton. * <p> * This involves generation of the appropriate acceptance condition * and making sure that the transition function is complete. * </p> * <p> * The DBA can also be complemented on the fly * (by modifying the acceptance condition of the DRA). The resulting DRA can then be * regarded as a Streett automaton of the original DBA. * @param nba the NBA, the transitions have to be deterministic! * @param complement complement the DBA? * @return a shared_ptr to the created DRA */public static DRA dba2dra(NBA nba) { return(dba2dra(nba, false)); }
public static void dba2dra(NBA nba, DRA dra_result, bool complement) { //complement=false DRA dra = dra_result; APSet ap_set = dra.getAPSet();; dra.acceptance().newAcceptancePair(); for (int i = 0; i < nba.size(); i++) { dra.newState(); if (complement) { // Final states -> U_0, all states -> L_0 if (nba[i].isFinal()) { dra.acceptance().stateIn_U(0, i); } dra.acceptance().stateIn_L(0, i); } else { // Final states -> L_0, U_0 is empty if (nba[i].isFinal()) { dra.acceptance().stateIn_L(0, i); } } } if (nba.getStartState() != null) { dra.setStartState(dra[nba.getStartState().getName()]); } DA_State sink_state = null; for (int i = 0; i < nba.size(); i++) { NBA_State nba_state = nba[i]; DA_State dra_from = dra[i]; //for (APSet::element_iterator label=ap_set->all_elements_begin();label!=ap_set->all_elements_end(); ++label) for (int label = ap_set.all_elements_begin(); label != ap_set.all_elements_end(); ++label) { BitSet to = nba_state.getEdge(new APElement(label)); int to_cardinality = 0; if (to != null) { to_cardinality = to.cardinality(); } DA_State dra_to = null; if (to == null || to_cardinality == 0) { // empty to -> go to sink state if (sink_state == null) { // we have to create the sink sink_state = dra.newState(); // if we complement, we have to add the sink to // L_0 if (complement) { sink_state.acceptance().addTo_L(0); } } dra_to = sink_state; } else if (to_cardinality == 1) { int to_index = to.nextSetBit(0); // std::cerr << "to: " << to_index << std::endl; dra_to = dra[to_index]; } else { // to_cardinality>1 ! throw new IllegalArgumentException("NBA is no DBA!"); } dra_from.edges().addEdge(new APElement(label), dra_to); } } if (sink_state != null) { // there is a sink state // make true-loop from sink state to itself //for (APSet::element_iterator label=ap_set->all_elements_begin();label!=ap_set->all_elements_end();++label) { for (int label = ap_set.all_elements_begin(); label != ap_set.all_elements_end(); ++label) { sink_state.edges().addEdge(new APElement(label), sink_state); } } }
/** * Convert a deterministic B點hi automaton * (a nondeterministic B點hi automaton NBA, where every transition * has at most one target state) to an equivalent deterministic * Rabin automaton. * <p> * This involves generation of the appropriate acceptance condition * and making sure that the transition function is complete. * </p> * <p> * The DBA can also be complemented on the fly * (by modifying the acceptance condition of the DRA). The resulting DRA can then be * regarded as a Streett automaton of the original DBA. * @param nba the NBA, the transitions have to be deterministic! * @param complement complement the DBA? * @return a shared_ptr to the created DRA */ public static DRA dba2dra(NBA nba) { return dba2dra(nba, false); }
/** Calculate the SCCs for Graph graph and save in result. */ public static void calculateSCCs(NBA graph, SCCs result, bool disjoint, APElement label) //, SuccessorAccess& successor_access { SCC_DFS scc_dfs = new SCC_DFS(graph, result, label); scc_dfs.calculate(disjoint); }
/** Calculate the stutter closure for the NBA, for all symbols. * @param nba the NBA */ public static NBA stutter_closure(NBA nba) { APSet apset = nba.getAPSet_cp(); NBA nba_result_ptr = new NBA(apset); NBA result = nba_result_ptr; int element_count = apset.powersetSize(); Debug.Assert(nba.getStartState() != null); int start_state = nba.getStartState().getName(); for (int i = 0; i < nba.size(); i++) { int st = result.nba_i_newState(); Debug.Assert(st == i); if (st == start_state) { result.setStartState(result[st]); } if (nba[st].isFinal()) { result[st].setFinal(true); } } for (int i = 0; i < nba.size(); i++) { for (int j = 0; j < element_count; j++) { int st = result.nba_i_newState(); Debug.Assert(st == nba.size() + (i*element_count) + j); result[st].addEdge(new APElement(j), result[i]); result[st].addEdge(new APElement(j), result[st]); } } List<List<BitSet>> reachable = new List<List<BitSet>>(); //reachable.resize(element_count); Ultility.resize(reachable, element_count); for (int j = 0; j < element_count; j++) { //NBAEdgeSuccessors edge_successor = new NBAEdgeSuccessors(new APElement(j)); SCCs scc = new SCCs(); GraphAlgorithms.calculateSCCs(nba, scc, true, new APElement(j)); //,edge_successor reachable[j] = scc.getReachabilityForAllStates(); #if VERBOSE std::cerr << "SCCs for " << APElement(j).toString(*apset) << std::endl; std::cerr << scc << std::endl; std::cerr << " Reachability: "<< std::endl; std::vector<BitSet>& reach=*reachable[j]; for (unsigned int t=0; t < reach.size(); t++) { std::cerr << t << " -> " << reach[t] << std::endl; } std::cerr << " ---\n"; #endif } for (int i = 0; i < nba.size(); i++) { NBA_State from = result[i]; for (int j = 0; j < element_count; j++) { BitSet result_to = new BitSet(); BitSet to = nba[i].getEdge(new APElement(j)); //for (BitSetIterator it=BitSetIterator(*to);it!=BitSetIterator::end(*to);++it) for (int it = BitSetIterator.start(to); it != BitSetIterator.end(to); it = BitSetIterator.increment(to, it)) { int to_state = it; // We can go directly to the original state result_to.set(to_state); // We can also go to the corresponding stutter state instead int stutter_state = nba.size() + (to_state*element_count) + j; result_to.set(stutter_state); // ... and then we can go directly to all the states that are j-reachable from to result_to.Union(reachable[j][to_state]); } from.getEdge(new APElement(j)).Assign(result_to); } } //for (int i=0; i<reachable.size(); ++i) { // delete reachable[i]; // } return nba_result_ptr; }
public EdgeCreator(int from, int to, NBA nba) { _from = from; _to = to; _nba = nba; }
//=0 /** * Convert the NBA to a DRA using Safra's algorithm, using stuttering * @param nba the NBA * @param dra_result the result DRA * @param limit limit for the size of the DRA */ //template < typename NBA_t, typename DRA_t > void convert_safra_stuttered(NBA nba, DRA dra_result, int limit) { SafraAlgorithm safras_algo = new SafraAlgorithm(nba, _options); StutteredNBA2DA nba2dra_stuttered = new StutteredNBA2DA(_detailed_states, _stutter_information); nba2dra_stuttered.convert(safras_algo, dra_result, limit); }
//=0 public void convert(NBA nba, DRA dra_result, int limit) { if (nba.size() == 0 || nba.getStartState() == null) { // the NBA is empty -> construct DRA that is empty dra_result.constructEmpty(); return; } if (_options.dba_check && nba.isDeterministic()) { DBA2DRA.dba2dra(nba, dra_result); return; } if (_options.stutter_closure) { if (_stutter_information != null && !_stutter_information.isCompletelyInsensitive()) { //std::cerr << //"WARNING: NBA might not be 100% stutter insensitive, applying stutter closure can create invalid results!" << //std::endl; } NBA nba_closed = NBAStutterClosure.stutter_closure(nba); if (can_stutter()) { convert_safra_stuttered(nba_closed, dra_result, limit); return; } convert_safra(nba_closed, dra_result, limit); return; } if (can_stutter()) { convert_safra_stuttered(nba, dra_result, limit); return; } convert_safra(nba, dra_result, limit); return; }
/** Translate LTL -> NBA */ public void generateNBA() { if (_nba == null) { _nba = _sched.getLTL2DRA().ltl2nba(_ltl, buchiAutomata); } }
public static void dba2dra(NBA nba, DRA dra_result, bool complement) { //complement=false DRA dra = dra_result; APSet ap_set = dra.getAPSet(); ; dra.acceptance().newAcceptancePair(); for (int i = 0; i < nba.size(); i++) { dra.newState(); if (complement) { // Final states -> U_0, all states -> L_0 if (nba[i].isFinal()) { dra.acceptance().stateIn_U(0, i); } dra.acceptance().stateIn_L(0, i); } else { // Final states -> L_0, U_0 is empty if (nba[i].isFinal()) { dra.acceptance().stateIn_L(0, i); } } } if (nba.getStartState() != null) { dra.setStartState(dra[nba.getStartState().getName()]); } DA_State sink_state = null; for (int i = 0; i < nba.size(); i++) { NBA_State nba_state = nba[i]; DA_State dra_from = dra[i]; //for (APSet::element_iterator label=ap_set->all_elements_begin();label!=ap_set->all_elements_end(); ++label) for (int label = ap_set.all_elements_begin(); label != ap_set.all_elements_end(); ++label) { BitSet to = nba_state.getEdge(new APElement(label)); int to_cardinality = 0; if (to != null) { to_cardinality = to.cardinality(); } DA_State dra_to = null; if (to == null || to_cardinality == 0) { // empty to -> go to sink state if (sink_state == null) { // we have to create the sink sink_state = dra.newState(); // if we complement, we have to add the sink to // L_0 if (complement) { sink_state.acceptance().addTo_L(0); } } dra_to = sink_state; } else if (to_cardinality == 1) { int to_index = to.nextSetBit(0); // std::cerr << "to: " << to_index << std::endl; dra_to = dra[to_index]; } else { // to_cardinality>1 ! throw new IllegalArgumentException("NBA is no DBA!"); } dra_from.edges().addEdge(new APElement(label), dra_to); } } if (sink_state != null) { // there is a sink state // make true-loop from sink state to itself //for (APSet::element_iterator label=ap_set->all_elements_begin();label!=ap_set->all_elements_end();++label) { for (int label = ap_set.all_elements_begin(); label != ap_set.all_elements_end(); ++label) { sink_state.edges().addEdge(new APElement(label), sink_state); } } }
/** Constructor. * @param nba the NBA to be analyzed */ public NBAAnalysis(NBA nba) { _nba = nba; }
/** * Convert an LTL formula to an NBA * @param ltl * @return a pointer to the created NBA (caller gets ownership). */ public static NBA ltl2nba(LTLFormula ltl, BuchiAutomata buchiAutomata) { // Create canonical APSet (with 'p0', 'p1', ... as AP) //LTLFormula ltl_canonical = ltl.copy(); //APSet canonical_apset = ltl.getAPSet().createCanonical(); // ltl_canonical.switchAPSet(canonical_apset); //AnonymousTempFile spin_outfile; //std::vector<std::string> arguments; //arguments.push_back("-f"); //arguments.push_back(ltl_canonical->toStringInfix()); //arguments.insert(arguments.end(), _arguments.begin(),_arguments.end()); //const char *program_path=_path.c_str(); //RunProgram spin(program_path, // arguments, // false, // 0, // &spin_outfile, // 0); //int rv=spin.waitForTermination(); //if (rv==0) { // NBA_t *result_nba(new NBA_t(canonical_apset)); // FILE *f=spin_outfile.getInFILEStream(); // if (f==NULL) { //throw Exception(""); // } // int rc=nba_parser_promela::parse(f, result_nba); // fclose(f); // if (rc!=0) { //throw Exception("Couldn't parse PROMELA file!"); // } NBA result_nba = new NBA(ltl.getAPSet()); //////////////////////////////////////////////////////////// //todo: create the NBA from the BA // // //////////////////////////////////////////////////////////// NBABuilder builder = new NBABuilder(result_nba); //int current_state = 0; //bool current_state_valid=false; //foreach (string state in buchiAutomata.States) //{ // if (buchiAutomata.InitialStates.Contains(state)) // { // int current_state = builder.findOrAddState(state); // if (buchiAutomata.InitialStates.Contains(state)) // { // builder.setStartState(current_state); // } // } //} foreach (string state in buchiAutomata.States) { //if (!buchiAutomata.InitialStates.Contains(state)) { ////s.AppendLine(state); //if (current_state_valid) { // builder.addAdditionalNameToState(state, current_state); //} //else //{ int current_state = builder.findOrAddState(state); //std::string& label=$1; //if (label.find("accept") != std::string::npos) { if (state.EndsWith(Constants.ACCEPT_STATE)) { builder.setFinal(current_state); } //if (label.find("accept_all") != std::string ::npos) //{ // // dirty hack: accept_all + skip -> trueloop // builder.setFinal(current_state); // builder.addEdge(current_state, current_state, std::string ("t")); //} if (buchiAutomata.InitialStates.Contains(state)) { builder.setStartState(current_state); } //current_state_valid = true; //} } } //s.AppendLine("Transitions"); foreach (Transition transition in buchiAutomata.Transitions) { int from = builder.findOrAddState(transition.FromState); int to = builder.findOrAddState(transition.ToState); builder.addEdge(from, to, transition.labels); } // switch back to original APSet //result_nba.switchAPSet(ltl.getAPSet()); //todo: //construct the NBA here return(result_nba); }