/* * Transformation LTL formulae to Buchi automata * - implementation of helping functions * * Milan Jaros - xjaros1@fi.muni.cz * */ #include #include "support_dve.hh" //#include "error/error.hh" //#include "deb/deb.hh" #ifndef DOXYGEN_PROCESSING using namespace divine; using namespace std; #endif //DOXYGEN_PROCESSING map *at_props = 0; // atomicke propozice void divine::reg_ltl_at_props(map *p_AP) { at_props = p_AP; } bool divine::read_ltl_file(istream& fr, list& L_ltl, list >& L_prop) { if (!L_ltl.empty()) L_ltl.erase(L_ltl.begin(), L_ltl.end()); if (!L_prop.empty()) L_prop.erase(L_prop.begin(), L_prop.end()); int stav = 0; string s, p1, p2;; char c; LTL_parse_t L; map M; while (!fr.eof()) { switch (stav) { case 0: // mimo formuli getline(fr, s, '{'); if (fr.eof()) return(true); getline(fr, s, '{'); getline(fr, s, '}'); L.nacti(s); M.erase(M.begin(), M.end()); stav = 1; break; case 1: // nacitani propozic do { fr >> c; } while ((!fr.eof()) && isspace(c)); if (fr.eof()) return(false); if (c == '}') { L_ltl.push_back(L); L_prop.push_back(M); stav = 0; break; } p1 = c; fr >> c; while (!fr.eof() && (c != ':') && (!isspace(c))) { p1 += c; fr >> c; } if (c != ':') getline(fr, s, ':'); if (fr.eof()) return(false); fr >> c; if ((c != '=') || fr.eof()) return(false); fr >> c; while (!fr.eof() && isspace(c)) fr >> c; if (fr.eof()) return(false); p2 = c; getline(fr, s, ';'); if (fr.eof()) return(false); p2 += s; M[p1] = p2; } } if (stav == 0) return(true); else return(false); } string print_formul(LTL_formul_t F) { bool neg; string prop, s = ""; map::iterator p_i; if (F.get_literal(neg, prop)) { if (!neg) s = "not "; if (at_props != 0) { p_i = at_props->find(prop); if (p_i == at_props->end()) { s += prop; } else { if (!neg) s += "("; s += p_i->second; if (!neg) s += ")"; } } else { s += prop; } return(s); } else { return(""); } } string print_literal(LTL_literal_t Lit) { string s = ""; map::iterator p_i; if (!Lit.negace) s = "not "; if (at_props != 0) { p_i = at_props->find(Lit.predikat); if (p_i == at_props->end()) { s += Lit.predikat; } else { if (!Lit.negace) s += "("; s += p_i->second; if (!Lit.negace) s += ")"; } } else { s += Lit.predikat; } return(s); } bool open_file(string file_name, fstream& fr, fstream& fw, int n = 0) { string jm_r, jm_w; string pripona_fw; int l; if (n == 0) { pripona_fw = ".prop.dve"; } else { char pom[10]; sprintf(pom, "%d", n); pripona_fw = ".prop"; pripona_fw += pom; pripona_fw += ".dve"; } l = file_name.length(); if (l > 4) { if ((file_name[l-4] == '.') && (file_name[l-3] == 'd') && (file_name[l-2] == 'v') && (file_name[l-1] == 'e')) { jm_r = file_name; file_name.erase(l-4); jm_w = file_name + pripona_fw; } else { jm_r = file_name + ".dve"; jm_w = file_name + pripona_fw; } } else { jm_r = file_name + ".dve"; jm_w = file_name + pripona_fw; } fr.open(jm_r.c_str(), ios::in); if (!fr) { cerr << "Soubor " << jm_r << " neexistuje" << endl; return(false); } fw.open(jm_w.c_str(), ios::out); if (!fw) { fr.close(); cerr << "Do souboru " << jm_w << " nelze zapisovat" << endl; return(false); } return(true); } bool copy_file(istream& fr, ostream& fw) { string s; size_t stav = 0, i; size_t npos = string::npos; while (!fr.eof()) { getline(fr, s); switch (stav) { case 0: // mimo definici procesu i = s.find("process"); if (i != npos) { i = s.find("{"); if (i != npos) { stav = 1; } else { stav = 2; } fw << s << endl; break; } i = s.find("system"); if (i == npos) { fw << s << endl; } break; case 1: // i = s.find("{"); if (i != npos) { stav = 2; } fw << s << endl; break; case 2: // v definici procesu i = s.find("{"); if (i != npos) { i = s.find("}"); if (i == npos) { stav = 3; } } else { i = s.find("}"); if (i != npos) { stav = 0; } } fw << s << endl; break; case 3: // v definici procesu - zavorka } i = s.find("}"); if (i != npos) { stav = 2; } fw << s << endl; break; } } return(true); } #ifndef CC_ONLY_OPT void divine::output_to_file(const ltl_graph_t& G, string file_name, int n) { fstream(fr); fstream(fw); if (!open_file(file_name, fr, fw, n)) { return; } if (!copy_file(fr, fw)) { return; } output(G, fw); fw << endl << "system async property LTL_property;" << endl; fr.close(); fw.close(); } #endif void divine::output_to_file(const BA_graph_t& G, string file_name, int n) { fstream(fr); fstream(fw); if (!open_file(file_name, fr, fw, n)) { return; } if (!copy_file(fr, fw)) { return; } output(G, fw); fw << endl << "system async property LTL_property;" << endl; fr.close(); fw.close(); } #ifndef CC_ONLY_OPT void divine::output(const ltl_graph_t& G, ostream& fw) { list LN; list::const_iterator ln_b, ln_e, ln_i; list LN_all; list::const_iterator l_b, l_e, l_i; LTL_set_acc_set_t::const_iterator sas_b, sas_e, sas_i; LTL_acc_set_t::const_iterator as_b, as_e, as_i; LTL_label_t LL; LTL_label_t::const_iterator lf_b, lf_e, lf_i; fw << "process LTL_property {" << endl; fw << "state q0"; G.get_all_gba_nodes(LN_all); l_b = LN_all.begin(); l_e = LN_all.end(); for (l_i = l_b; l_i != l_e; l_i++) { fw << ", q" << *l_i; } fw << ";" << endl; fw << "init q0;" << endl; sas_b = G.get_gba_set_acc_set().begin(); sas_e = G.get_gba_set_acc_set().end(); for (sas_i = sas_b; sas_i != sas_e; sas_i++) { fw << "accept "; as_b = sas_i->begin(); as_e = sas_i->end(); fw << "q" << (*as_b); as_i = as_b; as_i++; for ( ; as_i != as_e; as_i++) { fw << ", q" << (*as_i); } fw << ";" << endl; } bool b; G.get_gba_init_nodes(LN); ln_b = LN.begin(); ln_e = LN.end(); b = false; for (ln_i = ln_b; ln_i != ln_e; ln_i++) { if (b) { fw << "," << endl; } else { fw << "trans" << endl; b = true; } fw << "q0 -> q" << ln_i->name << " {"; ln_i->get_label(LL); if (!LL.empty()) { lf_b = LL.begin(); lf_e = LL.end(); fw << " guard " << print_literal(*lf_b); lf_i = lf_b; lf_i++; for ( ; lf_i != lf_e; lf_i++) { fw << " && " << print_literal(*lf_i); } fw << "; "; } fw << "}"; } for (l_i = l_b; l_i != l_e; l_i++) { G.get_gba_node_adj(*l_i, LN); ln_b = LN.begin(); ln_e = LN.end(); for (ln_i = ln_b; ln_i != ln_e; ln_i++) { fw << "," << endl; fw << "q" << *l_i << " -> q" << ln_i->name << " {"; ln_i->get_label(LL); if (!LL.empty()) { lf_b = LL.begin(); lf_e = LL.end(); fw << " guard " << print_literal(*lf_b); lf_i = lf_b; lf_i++; for ( ; lf_i != lf_e; lf_i++) { fw << " && " << print_literal(*lf_i); } fw << "; "; } fw << "}"; } } if (b) fw << ";" << endl; fw << "}" << endl; } #endif void divine::output(const BA_graph_t& G, ostream& fw) { list LN_all, LN; list::const_iterator ln_b, ln_e, ln_i, l_b, l_e, l_i; list::const_iterator t_b, t_e, t_i; const KS_BA_node_t *p_N; LTL_label_t::const_iterator lf_b, lf_e, lf_i; bool b; LN = G.get_init_nodes(); if (LN.size() != 1) { cerr << "Graf ma " << LN.size() << " inicialnich stavu"; cerr << endl; return; } fw << "process LTL_property {" << endl; p_N = LN.front(); fw << "state "; b = false; LN_all = G.get_all_nodes(); ln_b = LN_all.begin(); ln_e = LN_all.end(); for (ln_i = ln_b; ln_i != ln_e; ln_i++) { if (b) fw << ", "; else b = true; fw << "q" << (*ln_i)->name; } fw << ";" << endl; fw << "init q" << p_N->name << ";" << endl; LN = G.get_accept_nodes(); l_b = LN.begin(); l_e = LN.end(); b = false; if (l_b != l_e) fw << "accept "; for (l_i = l_b; l_i != l_e; l_i++) { if (b) { fw << ", "; } else { b = true; } fw << "q" << (*l_i)->name; } if (l_b != l_e) fw << ";" << endl; b = false; for (ln_i = ln_b; ln_i != ln_e; ln_i++) { p_N = *ln_i; t_b = G.get_node_adj(p_N).begin(); t_e = G.get_node_adj(p_N).end(); for (t_i = t_b; t_i != t_e; t_i++) { if (!b) fw << "trans" << endl; if (b) fw << "," << endl; else b = true; fw << "q" << p_N->name << " -> q" << t_i->target->name << " {"; if ( !(t_i->t_label.empty()) ) { lf_b = t_i->t_label.begin(); lf_e = t_i->t_label.end(); fw << " guard " << print_literal(*lf_b); lf_i = lf_b; lf_i++; for ( ; lf_i != lf_e; lf_i++) { fw << " && " << print_literal(*lf_i); } fw << "; "; } fw << "}"; } } if (b) fw << ";" << endl; fw << "}" << endl; }