/** Get the SCCs for the NBA * @return the SCCs */ public SCCs getSCCs() { if (_sccs == null) { _sccs = new SCCs(); GraphAlgorithms.calculateSCCs(_nba, _sccs, false, null); } return(_sccs); }
/** * Calculate the set of states that are accepting and have a true self loop. */ public void calculateAcceptingTrueLoops() { _accepting_true_loops = new BitSet(); //BitSet isAcceptingTrueLoop= *_accepting_true_loops; BitSet isAcceptingTrueLoop = _accepting_true_loops;////////changed SCCs sccs = getSCCs(); for (int scc = 0; scc < sccs.countSCCs(); ++scc) { if (sccs[scc].cardinality() == 1) { int state_id = sccs[scc].nextSetBit(0); NBA_State state = _nba[state_id]; if (!state.isFinal()) { // not final, consider next continue; } if (!sccs.successors(scc).isEmpty())//////////note here { // there are edges leaving this state, consider next continue; } bool no_empty_to = true; if (sccs.stateIsReachable(state_id, state_id)) { // state has at least one self-loop // we have to check that there is no edge with empty To //for (typename NBA_t::edge_iterator eit=state->edges_begin(); eit!=state->edges_end(); ++eit) //BitSet[] edges = state._edge_manager._container._storage; //foreach (BitSet eit in edges) for (KeyValuePair <APElement, BitSet> eit = state.edges_begin(); !state.edges_end(); eit = state.increment()) { BitSet edge = eit.Value; if (edge.isEmpty()) { // not all edges lead back to the state... no_empty_to = false; break; } } if (no_empty_to) { // When we are here the state is a final true loop isAcceptingTrueLoop.set(state_id); // std::cerr << "True Loop: " << state_id << std::endl; } } } } }
/** 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>(); }
/** * Remove states from the set of accepting (final) states when this is redundant. * @param sccs the SCCs of the NBA */ public void removeRedundantFinalStates(SCCs sccs) { for (int scc = 0; scc < sccs.countSCCs(); ++scc) { if (sccs[scc].cardinality() == 1) { int state_id = sccs[scc].nextSetBit(0); NBA_State state = this[state_id]; if (state.isFinal()) { if (!sccs.stateIsReachable(state_id, state_id)) { // The state is final and has no self-loop // -> the final flag is redundant state.setFinal(false); // std::cerr << "Removing final flag for " << state_id << std::endl; } } } } }
/** * Calculates BitSet which specifies which states in the NBA * only have accepting successors. */ public void calculateStatesWithAllSuccAccepting() { _allSuccAccepting = new BitSet(); BitSet result = _allSuccAccepting; SCCs sccs = getSCCs(); List <bool> scc_all_final = new List <bool>(); Ultility.resize(scc_all_final, sccs.countSCCs()); for (int i = 0; i < scc_all_final.Count; i++) { scc_all_final[i] = false; } for (int i = sccs.countSCCs(); i > 0; --i) { // go backward in topological order... int scc = (sccs.topologicalOrder())[i - 1]; BitSet states_in_scc = sccs[scc]; // check to see if all states in this SCC are final scc_all_final[scc] = true; //for (BitSetIterator it=BitSetIterator(states_in_scc);it!=BitSetIterator::end(states_in_scc);++it) for (int it = BitSetIterator.start(states_in_scc); it != BitSetIterator.end(states_in_scc); it = BitSetIterator.increment(states_in_scc, it)) { if (!_nba[it].isFinal()) { scc_all_final[scc] = false; break; } } bool might_be_final = false; if (scc_all_final[scc] == false) { if (states_in_scc.length() == 1) { // there is only one state in this scc ... int state = states_in_scc.nextSetBit(0); if (sccs.stateIsReachable(state, state) == false) { // ... and it doesn't loop to itself might_be_final = true; } } } if (scc_all_final[scc] == true || might_be_final) { // Check to see if all successors are final... bool all_successors_are_final = true; BitSet scc_succ = sccs.successors(scc); //for (BitSetIterator it=BitSetIterator(scc_succ); it!=BitSetIterator::end(scc_succ); ++it) { for (int it = BitSetIterator.start(scc_succ); it != BitSetIterator.end(scc_succ); it = BitSetIterator.increment(scc_succ, it)) { if (!scc_all_final[it]) { all_successors_are_final = false; break; } } if (all_successors_are_final) { // Add all states in this SCC to the result-set result.Or(states_in_scc); if (might_be_final) { scc_all_final[scc] = true; } } } } }
/** Check if the NBA is empty. * @return true iff the NBA has no accepting run. */ public bool emptinessCheck() { SCCs sccs = getSCCs(); #if VERBOSE std::cerr << sccs << "\n"; std::cerr << " Reachability: " << std::endl; std::vector <BitSet> *reachable = sccs.getReachabilityForAllStates(); for (unsigned int t = 0; t < reachable->size(); t++) { std::cerr << t << " -> " << (*reachable)[t] << std::endl; } delete reachable; #endif for (int scc = 0; scc < sccs.countSCCs(); ++scc) { BitSet states_in_scc = sccs[scc]; // check to see if there is an accepting state in this SCC //for (BitSetIterator it=BitSetIterator(states_in_scc); it!=BitSetIterator::end(states_in_scc); ++it) for (int it = BitSetIterator.start(states_in_scc); it != BitSetIterator.end(states_in_scc); it = BitSetIterator.increment(states_in_scc, it)) { int state = it; #if VERBOSE std::cerr << "Considering state " << state << std::endl; #endif if (_nba[state].isFinal()) { // check to see if this SCC is a trivial SCC (can't reach itself) #if VERBOSE std::cerr << " +final"; std::cerr << " " << states_in_scc.cardinality(); #endif if (states_in_scc.cardinality() == 1) { // there is only one state in this scc ... #if VERBOSE std::cerr << " +single"; #endif if (sccs.stateIsReachable(state, state) == false) { // ... and it doesn't loop to itself // -> can not guarantee accepting run #if VERBOSE std::cerr << " -no_loop" << std::endl; #endif continue; } } // if we are here, the SCC has more than 1 state or // exactly one self-looping state // -> accepting run #if VERBOSE std::cerr << "+acc" << std::endl; #endif // check that SCC can be reached from initial state Debug.Assert(_nba.getStartState() != null); if (sccs.stateIsReachable(_nba.getStartState().getName(), state)) { #if VERBOSE std::cerr << "Found accepting state = " << state << std::endl; #endif return(false); } #if VERBOSE std::cerr << "Not reachable!" << std::endl; #endif continue; } } } return(true); }
/** 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; }
/** 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; }
/** 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); }
/** 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); }
//, 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); }
/** 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 }
// /** 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>(); }
/** 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); }