/** Node visitor */ public void visit(SafraTree tree, SafraTreeNode node) { bool all_final = true; //for (BitSetIterator it=BitSetIterator(node->getLabeling());it!=BitSetIterator::end(node->getLabeling());++it) //BitSet label_this = node.getLabeling(); //for (int it = 0; it < label_this.Count; it++) for (int it = BitSetIterator.start(node.getLabeling()); it != BitSetIterator.end(node.getLabeling()); it = BitSetIterator.increment(node.getLabeling(), it)) { //// if (!_nba_states_with_all_succ_final.get(*it)) { if (!_nba_states_with_all_succ_final.get(it)) { all_final = false; break; } } if (all_final) { // remove all children of node & set final flag STVisitor_remove_subtree stv_remove = new STVisitor_remove_subtree(_tree_template); tree.walkChildrenPostOrder(stv_remove, node); node.setFinalFlag(); _success = true; } }
public List <BitSet> getReachabilityForAllStates() { //std::vector<BitSet>* v=new std::vector<BitSet>; //v->resize(_state_to_scc.size()); List <BitSet> v = new List <BitSet>(); Ultility.resizeExact(v, _state_to_scc.Count); for (int i = 0; i < _state_to_scc.Count; ++i) { int scc = state2scc(i); BitSet reachable_sccs = _reachability[scc]; BitSet reachable_states = new BitSet(); //for (BitSetIterator it(reachable_sccs); it != BitSetIterator::end(reachable_sccs); ++it) for (int it = BitSetIterator.start(reachable_sccs); it != BitSetIterator.end(reachable_sccs); it = BitSetIterator.increment(reachable_sccs, it)) { // union with all states from the reachable scc reachable_states.Union(_sccs[it]); } v[i] = reachable_states; //std::cerr << "from "<<i<<": "<<reachable_states<<std::endl; } return(v); }
/** * 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 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); }
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 Directed Acyclical Graph (DAG) */ public void calculateDAG() { //_result._dag.Clear(); //_result._dag.resize(_result.countSCCs()); Ultility.resizeExact(_result._dag, _result.countSCCs()); //_result._reachability.resize(_result.countSCCs()); Ultility.resizeExact(_result._reachability, _result.countSCCs()); List <int> in_degree = new List <int>(_result.countSCCs()); Ultility.resizeExact(in_degree, _result.countSCCs()); for (int scc = 0; scc < _result.countSCCs(); ++scc) { _result._reachability[scc] = new BitSet(); _result._dag[scc] = new BitSet(); BitSet states_in_scc = _result[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 from_state = it; if (_labelMark == null) { //for (typename SuccessorAccess::successor_iterator succ_it=_successor_access.begin(_graph, from_state);succ_it!=_successor_access.end(_graph, from_state); ++succ_it) for (KeyValuePair <APElement, BitSet> it_set = _graph[from_state].edges_begin(); !_graph[from_state].edges_end(); it_set = _graph[from_state].increment()) { for (int succ_it = BitSetIterator.start(it_set.Value); succ_it != BitSetIterator.end(it_set.Value); succ_it = BitSetIterator.increment(it_set.Value, succ_it)) { int to_state = succ_it; int to_scc = _result.state2scc(to_state); if (to_scc != scc) { // Only successor in the DAG if not the same scc if (!_result._dag[scc].get(to_scc)) { // This SCC is a new successor, increment in_degree in_degree[to_scc]++; _result._dag[scc].set(to_scc); } } // Reachability _result._reachability[scc].set(to_scc); } } } else { BitSet it_set = _graph[from_state].getEdge(_labelMark); //for (typename SuccessorAccess::successor_iterator succ_it=_successor_access.begin(_graph, from_state);succ_it!=_successor_access.end(_graph, from_state); ++succ_it) for (int succ_it = BitSetIterator.start(it_set); succ_it != BitSetIterator.end(it_set); succ_it = BitSetIterator.increment(it_set, succ_it)) { int to_state = succ_it; int to_scc = _result.state2scc(to_state); if (to_scc != scc) { // Only successor in the DAG if not the same scc if (!_result._dag[scc].get(to_scc)) { // This SCC is a new successor, increment in_degree in_degree[to_scc]++; _result._dag[scc].set(to_scc); } } // Reachability _result._reachability[scc].set(to_scc); } } } } bool progress = true; int cnt = 0; //_result._topological_order.Clear(); //_result._topological_order.resize(_result.countSCCs()); Ultility.resizeExact(_result._topological_order, _result.countSCCs()); List <int> sort = new List <int>(_result.countSCCs()); Ultility.resizeExact(sort, _result.countSCCs()); while (progress) { progress = false; for (int scc = 0; scc < _result.countSCCs(); ++scc) { if (in_degree[scc] == 0) { sort[scc] = cnt++; progress = true; in_degree[scc] = -1; //for (BitSetIterator it_neighbors= BitSetIterator(_result._dag[scc]); it_neighbors!=BitSetIterator::end(_result._dag[scc]); ++it_neighbors) for (int it_neighbors = BitSetIterator.start(_result._dag[scc]); it_neighbors != BitSetIterator.end(_result._dag[scc]); it_neighbors = BitSetIterator.increment(_result._dag[scc], it_neighbors)) { int scc_to = it_neighbors; in_degree[scc_to]--; } } } } for (int i = 0; i < _result.countSCCs(); i++) { _result._topological_order[sort[i]] = i; } // traverse SCCs in reverse topological order for (int i = _result.countSCCs(); i > 0; --i) { int cur_scc = _result._topological_order[i - 1]; BitSet reaches = _result._reachability[cur_scc]; //for (BitSetIterator it_neighbors= BitSetIterator(_result._dag[cur_scc]); it_neighbors!=BitSetIterator::end(_result._dag[cur_scc]);++it_neighbors) { for (int it_neighbors = BitSetIterator.start(_result._dag[cur_scc]); it_neighbors != BitSetIterator.end(_result._dag[cur_scc]); it_neighbors = BitSetIterator.increment(_result._dag[cur_scc], it_neighbors)) { int scc_to = it_neighbors; reaches.Union(_result._reachability[scc_to]); } } }
/** Visit a state (perform DFS) */ public void visit(int v) { SCC_DFS_Data sdd = new SCC_DFS_Data(); sdd.dfs_nr = current_dfs_nr++; sdd.root_index = v; sdd.inComponent = false; _stack.Push(v); //todo: be careful of the following swap //_dfs_data[v].reset(sdd); //Ultility.swap(_dfs_data[v], sdd); _dfs_data[v] = sdd; //for (typename SuccessorAccess::successor_iterator succ_it=_successor_access.begin(_graph, v);succ_it!=_successor_access.end(_graph, v); ++succ_it) if (_labelMark == null) { for (KeyValuePair <APElement, BitSet> it_set = _graph[v].edges_begin(); !_graph[v].edges_end(); it_set = _graph[v].increment()) { for (int succ_it = BitSetIterator.start(it_set.Value); succ_it != BitSetIterator.end(it_set.Value); succ_it = BitSetIterator.increment(it_set.Value, succ_it)) { int w = succ_it; if (_dfs_data[w] == null) //.get() { // not yet visited visit(w); } SCC_DFS_Data sdd_w = _dfs_data[w]; //.get(); if (sdd_w.inComponent == false) { int dfs_nr_root_v = _dfs_data[sdd.root_index].dfs_nr; int dfs_nr_root_w = _dfs_data[sdd_w.root_index].dfs_nr; if (dfs_nr_root_v > dfs_nr_root_w) { sdd.root_index = sdd_w.root_index; } } } } } else { BitSet it_set = _graph[v].getEdge(_labelMark); for (int succ_it = BitSetIterator.start(it_set); succ_it != BitSetIterator.end(it_set); succ_it = BitSetIterator.increment(it_set, succ_it)) { int w = succ_it; if (_dfs_data[w] == null) //.get() { // not yet visited visit(w); } SCC_DFS_Data sdd_w = _dfs_data[w]; //.get(); if (sdd_w.inComponent == false) { int dfs_nr_root_v = _dfs_data[sdd.root_index].dfs_nr; int dfs_nr_root_w = _dfs_data[sdd_w.root_index].dfs_nr; if (dfs_nr_root_v > dfs_nr_root_w) { sdd.root_index = sdd_w.root_index; } } } } if (sdd.root_index == v) { BitSet set = new BitSet(); int w; do { //w=_stack.Peek(); //.top(); w = _stack.Pop(); set.set(w); _result.setState2SCC(w, scc_nr); SCC_DFS_Data sdd_w = _dfs_data[w];//.get(); sdd_w.inComponent = true; } while (w != v); scc_nr = _result.addSCC(set) + 1; } }
/** * Generate a new DRA from a coloring */ DRA generateDRAfromColoring(DRA oldDRA, Coloring coloring, bool detailedStates) { DRA newDRA = oldDRA.createInstance(oldDRA.getAPSet()) as DRA; newDRA.acceptance().newAcceptancePairs(oldDRA.acceptance().size()); for (int color = 0; color < coloring.countColors(); ++color) { newDRA.newState(); } int old_start_state = oldDRA.getStartState().getName(); int start_state_color = coloring.state2color(old_start_state); newDRA.setStartState(newDRA.get(start_state_color)); APSet apset = newDRA.getAPSet(); for (int color = 0; color < coloring.countColors(); ++color) { DA_State new_state = newDRA.get(color); int old_state_representative = coloring.color2state(color); DA_State old_state = oldDRA[old_state_representative]; if (detailedStates) { BitSet old_states = coloring.color2states(color); // create new description... if (old_states.cardinality() == 1) { if (old_state.hasDescription()) { new_state.setDescription(old_state.getDescription()); } } else { //std::ostringstream s; //s << "<TABLE BORDER=\"1\" CELLBORDER=\"0\"><TR><TD>{</TD>"; StringBuilder s = new StringBuilder(@"<TABLE BORDER=\""1\"" CELLBORDER=\""0\""><TR><TD>{</TD>"); bool first = true; for (int it = BitSetIterator.start(old_states); it != BitSetIterator.end(old_states); it = BitSetIterator.increment(old_states, it)) { if (first) { first = false; } else { s.Append("<TD>,</TD>"); } s.Append("<TD>"); if (!oldDRA[it].hasDescription()) { s.Append(it); } else { s.Append(oldDRA[it].getDescription()); } s.Append("</TD>"); } s.Append("<TD>}</TD></TR></TABLE>"); new_state.setDescription(s.ToString()); ; } } // Create appropriate acceptance conditions int old_state_index = old_state.getName(); for (int i = 0; i < oldDRA.acceptance().size(); ++i) { if (oldDRA.acceptance().isStateInAcceptance_L(i, old_state_index)) { new_state.acceptance().addTo_L(i); } if (oldDRA.acceptance().isStateInAcceptance_U(i, old_state_index)) { new_state.acceptance().addTo_U(i); } } //for (APSet::element_iterator label=apset.all_elements_begin();label!=apset.all_elements_end();++label) for (int label = apset.all_elements_begin(); label != apset.all_elements_end(); ++label) { DA_State old_to = old_state.edges().get(new APElement(label)); int to_color = coloring.state2color(old_to.getName()); new_state.edges().addEdge(new APElement(label), newDRA.get(to_color)); } } return(newDRA); }