diff --git a/bin/autfilt.cc b/bin/autfilt.cc index 6be6d401a..53d642731 100644 --- a/bin/autfilt.cc +++ b/bin/autfilt.cc @@ -363,9 +363,9 @@ parse_opt(int key, char* arg, struct argp_state*) break; case 'x': { - const char* opt = extra_options.parse_options(arg); - if (opt) - error(2, 0, "failed to parse --options near '%s'", opt); + const char* opt = extra_options.parse_options(arg); + if (opt) + error(2, 0, "failed to parse --options near '%s'", opt); } break; case OPT_AP_N: @@ -376,15 +376,15 @@ parse_opt(int key, char* arg, struct argp_state*) break; case OPT_ACCEPT_WORD: try - { - opt->acc_words.push_back(spot::parse_word(arg, opt->dict) - ->as_automaton()); - } + { + opt->acc_words.push_back(spot::parse_word(arg, opt->dict) + ->as_automaton()); + } catch (const spot::parse_error& e) - { - error(2, 0, "failed to parse the argument of --accept-word:\n%s", - e.what()); - } + { + error(2, 0, "failed to parse the argument of --accept-word:\n%s", + e.what()); + } break; case OPT_ARE_ISOMORPHIC: opt->are_isomorphic = read_automaton(arg, opt->dict); @@ -420,27 +420,27 @@ parse_opt(int key, char* arg, struct argp_state*) break; case OPT_EQUIVALENT_TO: if (opt->equivalent_pos) - error(2, 0, "only one --equivalent-to option can be given"); + error(2, 0, "only one --equivalent-to option can be given"); opt->equivalent_pos = read_automaton(arg, opt->dict); opt->equivalent_neg = - spot::dtwa_complement(ensure_deterministic(opt->equivalent_pos)); + spot::dtwa_complement(ensure_deterministic(opt->equivalent_pos)); break; case OPT_INSTUT: if (!arg || (arg[0] == '1' && arg[1] == 0)) - opt_instut = 1; + opt_instut = 1; else if (arg[0] == '2' && arg[1] == 0) - opt_instut = 2; + opt_instut = 2; else - error(2, 0, "unknown argument for --instut: %s", arg); + error(2, 0, "unknown argument for --instut: %s", arg); break; case OPT_INCLUDED_IN: { - auto aut = ensure_deterministic(read_automaton(arg, opt->dict)); - aut = spot::dtwa_complement(aut); - if (!opt->included_in) - opt->included_in = aut; - else - opt->included_in = spot::product_or(opt->included_in, aut); + auto aut = ensure_deterministic(read_automaton(arg, opt->dict)); + aut = spot::dtwa_complement(aut); + if (!opt->included_in) + opt->included_in = aut; + else + opt->included_in = spot::product_or(opt->included_in, aut); } break; case OPT_INTERSECT: @@ -472,18 +472,18 @@ parse_opt(int key, char* arg, struct argp_state*) break; case OPT_MASK_ACC: { - for (auto res : to_longs(arg)) - { - if (res < 0) - error(2, 0, "acceptance sets should be non-negative:" - " --mask-acc=%ld", res); - if (static_cast(res) - > sizeof(spot::acc_cond::mark_t::value_t)) - error(2, 0, "this implementation does not support that many" - " acceptance sets: --mask-acc=%ld", res); - opt_mask_acc.set(res); - } - break; + for (auto res : to_longs(arg)) + { + if (res < 0) + error(2, 0, "acceptance sets should be non-negative:" + " --mask-acc=%ld", res); + if (static_cast(res) + > sizeof(spot::acc_cond::mark_t::value_t)) + error(2, 0, "this implementation does not support that many" + " acceptance sets: --mask-acc=%ld", res); + opt_mask_acc.set(res); + } + break; } case OPT_KEEP_STATES: { @@ -491,71 +491,71 @@ parse_opt(int key, char* arg, struct argp_state*) if (!values.empty()) opt_keep_states_initial = values[0]; for (auto res : values) - { - if (res < 0) - error(2, 0, "state ids should be non-negative:" - " --mask-acc=%ld", res); + { + if (res < 0) + error(2, 0, "state ids should be non-negative:" + " --mask-acc=%ld", res); // We don't know yet how many states the automata contain. if (opt_keep_states.size() <= static_cast(res)) opt_keep_states.resize(res + 1, false); - opt_keep_states[res] = true; - } - opt_rem_unreach = true; - break; + opt_keep_states[res] = true; + } + opt_rem_unreach = true; + break; } case OPT_PRODUCT_AND: { - auto a = read_automaton(arg, opt->dict); - if (!opt->product_and) - opt->product_and = std::move(a); - else - opt->product_and = spot::product(std::move(opt->product_and), - std::move(a)); + auto a = read_automaton(arg, opt->dict); + if (!opt->product_and) + opt->product_and = std::move(a); + else + opt->product_and = spot::product(std::move(opt->product_and), + std::move(a)); } break; case OPT_PRODUCT_OR: { - auto a = read_automaton(arg, opt->dict); - if (!opt->product_or) - opt->product_or = std::move(a); - else - opt->product_or = spot::product_or(std::move(opt->product_or), - std::move(a)); + auto a = read_automaton(arg, opt->dict); + if (!opt->product_or) + opt->product_or = std::move(a); + else + opt->product_or = spot::product_or(std::move(opt->product_or), + std::move(a)); } break; case OPT_RANDOMIZE: if (arg) - { - for (auto p = arg; *p; ++p) - switch (*p) - { - case 's': - randomize_st = true; - break; - case 't': - randomize_tr = true; - break; - default: - error(2, 0, "unknown argument for --randomize: '%c'", *p); - } - } + { + for (auto p = arg; *p; ++p) + switch (*p) + { + case 's': + randomize_st = true; + break; + case 't': + randomize_tr = true; + break; + default: + error(2, 0, "unknown argument for --randomize: '%c'", *p); + } + } else - { - randomize_tr = true; - randomize_st = true; - } + { + randomize_tr = true; + randomize_st = true; + } break; case OPT_REJECT_WORD: try - { - opt->rej_words.push_back(spot::parse_word(arg, opt->dict) - ->as_automaton()); - } + { + opt->rej_words.push_back(spot::parse_word(arg, opt->dict) + ->as_automaton()); + } catch (const spot::parse_error& e) - { - error(2, 0, "failed to parse the argument of --reject-word:\n%s", - e.what()); - } + { + error(2, 0, "failed to parse the argument of --reject-word:\n%s", + e.what()); + } break; case OPT_REM_AP: opt->rem_ap.add_ap(arg); @@ -621,7 +621,7 @@ namespace int process_automaton(const spot::const_parsed_aut_ptr& haut, - const char* filename) + const char* filename) { spot::stopwatch sw; sw.start(); @@ -630,30 +630,30 @@ namespace // never modify the original automaton (e.g. with // merge_edges()) and the statistics about it make sense. auto aut = ((automaton_format == Stats) || opt_name) - ? spot::make_twa_graph(haut->aut, spot::twa::prop_set::all()) - : haut->aut; + ? spot::make_twa_graph(haut->aut, spot::twa::prop_set::all()) + : haut->aut; // Preprocessing. if (opt_stripacc) - spot::strip_acceptance_here(aut); + spot::strip_acceptance_here(aut); if (opt_merge) - aut->merge_edges(); + aut->merge_edges(); if (opt_clean_acc || opt_rem_fin) - cleanup_acceptance_here(aut); + cleanup_acceptance_here(aut); if (opt_sep_sets) - separate_sets_here(aut); + separate_sets_here(aut); if (opt_complement_acc) - aut->set_acceptance(aut->acc().num_sets(), - aut->get_acceptance().complement()); + aut->set_acceptance(aut->acc().num_sets(), + aut->get_acceptance().complement()); if (opt_rem_fin) - aut = remove_fin(aut); + aut = remove_fin(aut); if (opt_dnf_acc) - aut->set_acceptance(aut->acc().num_sets(), - aut->get_acceptance().to_dnf()); + aut->set_acceptance(aut->acc().num_sets(), + aut->get_acceptance().to_dnf()); if (opt_cnf_acc) - aut->set_acceptance(aut->acc().num_sets(), - aut->get_acceptance().to_cnf()); + aut->set_acceptance(aut->acc().num_sets(), + aut->get_acceptance().to_cnf()); // Filters. @@ -664,46 +664,46 @@ namespace matched &= opt_accsets.contains(aut->acc().num_sets()); matched &= opt_ap_n.contains(aut->ap().size()); if (opt_is_complete) - matched &= is_complete(aut); + matched &= is_complete(aut); if (opt_is_deterministic) - matched &= is_deterministic(aut); + matched &= is_deterministic(aut); if (opt_is_deterministic) - matched &= is_deterministic(aut); + matched &= is_deterministic(aut); else if (opt_is_unambiguous) - matched &= is_unambiguous(aut); + matched &= is_unambiguous(aut); if (opt_is_terminal) - matched &= is_terminal_automaton(aut); + matched &= is_terminal_automaton(aut); else if (opt_is_weak) - matched &= is_weak_automaton(aut); + matched &= is_weak_automaton(aut); else if (opt_is_inherently_weak) - matched &= is_inherently_weak_automaton(aut); + matched &= is_inherently_weak_automaton(aut); if (opt->are_isomorphic) matched &= opt->isomorphism_checker->is_isomorphic(aut); if (opt_is_empty) - matched &= aut->is_empty(); + matched &= aut->is_empty(); if (opt->intersect) - matched &= !spot::product(aut, opt->intersect)->is_empty(); + matched &= !spot::product(aut, opt->intersect)->is_empty(); if (opt->included_in) - matched &= spot::product(aut, opt->included_in)->is_empty(); + matched &= spot::product(aut, opt->included_in)->is_empty(); if (opt->equivalent_pos) - matched &= spot::product(aut, opt->equivalent_neg)->is_empty() - && spot::product(dtwa_complement(ensure_deterministic(aut)), - opt->equivalent_pos)->is_empty(); + matched &= spot::product(aut, opt->equivalent_neg)->is_empty() + && spot::product(dtwa_complement(ensure_deterministic(aut)), + opt->equivalent_pos)->is_empty(); if (matched && !opt->acc_words.empty()) - for (auto& word_aut: opt->acc_words) - if (spot::product(aut, word_aut)->is_empty()) - { - matched = false; - break; - } + for (auto& word_aut: opt->acc_words) + if (spot::product(aut, word_aut)->is_empty()) + { + matched = false; + break; + } if (matched && !opt->rej_words.empty()) - for (auto& word_aut: opt->rej_words) - if (!spot::product(aut, word_aut)->is_empty()) - { - matched = false; - break; - } + for (auto& word_aut: opt->rej_words) + if (!spot::product(aut, word_aut)->is_empty()) + { + matched = false; + break; + } // Drop or keep matched automata depending on the --invert option if (matched == opt_invert) @@ -712,65 +712,65 @@ namespace // Postprocessing. if (opt_mask_acc) - aut = mask_acc_sets(aut, opt_mask_acc & aut->acc().all_sets()); + aut = mask_acc_sets(aut, opt_mask_acc & aut->acc().all_sets()); if (!opt->excl_ap.empty()) - aut = opt->excl_ap.constrain(aut, opt_simplify_exclusive_ap); + aut = opt->excl_ap.constrain(aut, opt_simplify_exclusive_ap); if (!opt->rem_ap.empty()) - aut = opt->rem_ap.strip(aut); + aut = opt->rem_ap.strip(aut); if (opt_destut) - aut = spot::closure(std::move(aut)); + aut = spot::closure(std::move(aut)); if (opt_instut == 1) - aut = spot::sl(std::move(aut)); + aut = spot::sl(std::move(aut)); else if (opt_instut == 2) - aut = spot::sl2(std::move(aut)); + aut = spot::sl2(std::move(aut)); if (!opt_keep_states.empty()) - aut = mask_keep_states(aut, opt_keep_states, opt_keep_states_initial); + aut = mask_keep_states(aut, opt_keep_states, opt_keep_states_initial); if (opt_rem_dead) - aut->purge_dead_states(); + aut->purge_dead_states(); else if (opt_rem_unreach) - aut->purge_unreachable_states(); + aut->purge_unreachable_states(); if (opt->product_and) - aut = spot::product(std::move(aut), opt->product_and); + aut = spot::product(std::move(aut), opt->product_and); if (opt->product_or) - aut = spot::product_or(std::move(aut), opt->product_or); + aut = spot::product_or(std::move(aut), opt->product_or); if (opt_decompose_strength) - { - aut = decompose_strength(aut, opt_decompose_strength); - if (!aut) - return 0; - } + { + aut = decompose_strength(aut, opt_decompose_strength); + if (!aut) + return 0; + } if (opt_sat_minimize) - { - aut = spot::sat_minimize(aut, opt_sat_minimize, sbacc); - if (!aut) - return 0; - } + { + aut = spot::sat_minimize(aut, opt_sat_minimize, sbacc); + if (!aut) + return 0; + } if (opt_complement) - aut = spot::dtwa_complement(ensure_deterministic(aut)); + aut = spot::dtwa_complement(ensure_deterministic(aut)); aut = post.run(aut, nullptr); if (randomize_st || randomize_tr) - spot::randomize(aut, randomize_st, randomize_tr); + spot::randomize(aut, randomize_st, randomize_tr); const double conversion_time = sw.stop(); if (opt->uniq) { auto tmp = - spot::canonicalize(make_twa_graph(aut, - spot::twa::prop_set::all())); + spot::canonicalize(make_twa_graph(aut, + spot::twa::prop_set::all())); if (!opt->uniq->emplace(tmp->edge_vector().begin() + 1, - tmp->edge_vector().end()).second) - return 0; + tmp->edge_vector().end()).second) + return 0; } ++match_count; @@ -778,7 +778,7 @@ namespace printer.print(aut, nullptr, filename, -1, conversion_time, haut); if (opt_max_count >= 0 && match_count >= opt_max_count) - abort_run = true; + abort_run = true; return 0; } @@ -796,19 +796,19 @@ namespace auto hp = spot::automaton_stream_parser(filename, opt_parse); int err = 0; while (!abort_run) - { - auto haut = hp.parse(opt->dict); - if (!haut->aut && haut->errors.empty()) - break; - if (haut->format_errors(std::cerr)) - err = 2; - if (!haut->aut) - error(2, 0, "failed to read automaton from %s", filename); - else if (haut->aborted) - err = std::max(err, aborted(haut, filename)); - else + { + auto haut = hp.parse(opt->dict); + if (!haut->aut && haut->errors.empty()) + break; + if (haut->format_errors(std::cerr)) + err = 2; + if (!haut->aut) + error(2, 0, "failed to read automaton from %s", filename); + else if (haut->aborted) + err = std::max(err, aborted(haut, filename)); + else process_automaton(haut, filename); - } + } return err; } }; @@ -820,7 +820,7 @@ main(int argc, char** argv) setup(argv); const argp ap = { options, parse_opt, "[FILENAMES...]", - argp_program_doc, children, nullptr, nullptr }; + argp_program_doc, children, nullptr, nullptr }; try { @@ -834,23 +834,23 @@ main(int argc, char** argv) pref = spot::postprocessor::Any; type = spot::postprocessor::Generic; if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) - exit(err); + exit(err); if (level_set && !pref_set) - pref = spot::postprocessor::Small; + pref = spot::postprocessor::Small; if (pref_set && !level_set) - level = spot::postprocessor::High; + level = spot::postprocessor::High; if (jobs.empty()) - jobs.emplace_back("-", true); + jobs.emplace_back("-", true); if (opt->are_isomorphic) - { - if (opt_merge) - opt->are_isomorphic->merge_edges(); - opt->isomorphism_checker = std::unique_ptr - (new spot::isomorphism_checker(opt->are_isomorphic)); - } + { + if (opt_merge) + opt->are_isomorphic->merge_edges(); + opt->isomorphism_checker = std::unique_ptr + (new spot::isomorphism_checker(opt->are_isomorphic)); + } spot::srand(opt_seed); @@ -862,7 +862,7 @@ main(int argc, char** argv) hoa_processor processor(post); if (processor.run()) - return 2; + return 2; } catch (const std::runtime_error& e) { diff --git a/bin/common_aoutput.cc b/bin/common_aoutput.cc index 03d7d01c3..086053e1e 100644 --- a/bin/common_aoutput.cc +++ b/bin/common_aoutput.cc @@ -136,7 +136,7 @@ static const argp_option options[] = }; const struct argp aoutput_argp = { options, parse_opt_aoutput, nullptr, nullptr, - nullptr, nullptr, nullptr }; + nullptr, nullptr, nullptr }; // Those can be overridden by individual tools. E.g. randaut has no // notion of input file, so %F and %L represent something else. @@ -181,8 +181,8 @@ static const argp_option io_options[] = }; const struct argp aoutput_io_format_argp = { io_options, nullptr, nullptr, - nullptr, nullptr, - nullptr, nullptr }; + nullptr, nullptr, + nullptr, nullptr }; static const argp_option o_options[] = { @@ -221,8 +221,8 @@ static const argp_option o_options[] = }; const struct argp aoutput_o_format_argp = { o_options, - nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr }; + nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr }; int parse_opt_aoutput(int key, char* arg, struct argp_state*) { @@ -249,15 +249,15 @@ int parse_opt_aoutput(int key, char* arg, struct argp_state*) case 's': automaton_format = Spin; if (type != spot::postprocessor::Monitor) - type = spot::postprocessor::BA; + type = spot::postprocessor::BA; automaton_format_opt = arg; break; case OPT_CHECK: automaton_format = Hoa; if (arg) - opt_check |= XARGMATCH("--check", arg, check_args, check_types); + opt_check |= XARGMATCH("--check", arg, check_args, check_types); else - opt_check |= check_all; + opt_check |= check_all; break; case OPT_LBTT: automaton_format = Lbtt; @@ -266,14 +266,14 @@ int parse_opt_aoutput(int key, char* arg, struct argp_state*) // because print_lbtt will raise an exception anyway. The // error message is slightly better in the current way. if (arg && (arg[0] != 't' || arg[1] != 0)) - error(2, 0, "unknown argument for --lbtt: '%s'", arg); + error(2, 0, "unknown argument for --lbtt: '%s'", arg); break; case OPT_NAME: opt_name = arg; break; case OPT_STATS: if (!*arg) - error(2, 0, "empty format string for --stats"); + error(2, 0, "empty format string for --stats"); stats = arg; automaton_format = Stats; break; @@ -288,23 +288,23 @@ void setup_default_output_format() if (auto val = getenv("SPOT_DEFAULT_FORMAT")) { static char const *const args[] = - { - "dot", "hoa", "hoaf", nullptr - }; + { + "dot", "hoa", "hoaf", nullptr + }; static automaton_format_t const format[] = - { - Dot, Hoa, Hoa - }; + { + Dot, Hoa, Hoa + }; auto eq = strchr(val, '='); if (eq) - { - val = strndup(val, eq - val); - automaton_format_opt = eq + 1; - } + { + val = strndup(val, eq - val); + automaton_format_opt = eq + 1; + } ARGMATCH_VERIFY(args, format); automaton_format = XARGMATCH("SPOT_DEFAULT_FORMAT", val, args, format); if (eq) - free(val); + free(val); } } @@ -320,24 +320,24 @@ automaton_printer::automaton_printer(stat_style input) void automaton_printer::print(const spot::twa_graph_ptr& aut, - spot::formula f, - // Input location for errors and statistics. - const char* filename, - int loc, - // Time and input automaton for statistics - double time, - const spot::const_parsed_aut_ptr& haut, - const char* csv_prefix, - const char* csv_suffix) + spot::formula f, + // Input location for errors and statistics. + const char* filename, + int loc, + // Time and input automaton for statistics + double time, + const spot::const_parsed_aut_ptr& haut, + const char* csv_prefix, + const char* csv_suffix) { if (opt_check) { if (opt_check & check_stutter) - spot::check_stutter_invariance(aut, f); + spot::check_stutter_invariance(aut, f); if (opt_check & check_unambiguous) - spot::check_unambiguous(aut); + spot::check_unambiguous(aut); if (opt_check & check_strength) - spot::check_strength(aut); + spot::check_strength(aut); } // Name the output automaton. @@ -353,11 +353,11 @@ automaton_printer::print(const spot::twa_graph_ptr& aut, { outputname.str(""); outputnamer.print(haut, aut, f, filename, loc, time, - csv_prefix, csv_suffix); + csv_prefix, csv_suffix); std::string fname = outputname.str(); auto p = outputfiles.emplace(fname, nullptr); if (p.second) - p.first->second.reset(new output_file(fname.c_str())); + p.first->second.reset(new output_file(fname.c_str())); out = &p.first->second->ostream(); } @@ -383,7 +383,7 @@ automaton_printer::print(const spot::twa_graph_ptr& aut, case Stats: statistics.set_output(*out); statistics.print(haut, aut, f, filename, loc, time, - csv_prefix, csv_suffix) << '\n'; + csv_prefix, csv_suffix) << '\n'; break; } flush_cout(); diff --git a/bin/common_aoutput.hh b/bin/common_aoutput.hh index e28d4d776..af0a6a581 100644 --- a/bin/common_aoutput.hh +++ b/bin/common_aoutput.hh @@ -75,25 +75,25 @@ class hoa_stat_printer: protected spot::stat_printer { public: hoa_stat_printer(std::ostream& os, const char* format, - stat_style input = no_input) + stat_style input = no_input) : spot::stat_printer(os, format) { if (input == aut_input) { - declare('A', &haut_acc_); - declare('C', &haut_scc_); - declare('E', &haut_edges_); - declare('G', &haut_gen_acc_); - declare('M', &haut_name_); - declare('S', &haut_states_); - declare('T', &haut_trans_); + declare('A', &haut_acc_); + declare('C', &haut_scc_); + declare('E', &haut_edges_); + declare('G', &haut_gen_acc_); + declare('M', &haut_name_); + declare('S', &haut_states_); + declare('T', &haut_trans_); } declare('<', &csv_prefix_); declare('>', &csv_suffix_); declare('F', &filename_); declare('L', &location_); if (input != ltl_input) - declare('f', &filename_); // Override the formula printer. + declare('f', &filename_); // Override the formula printer. declare('m', &aut_name_); declare('w', &aut_word_); } @@ -107,93 +107,93 @@ public: /// to be output. std::ostream& print(const spot::const_parsed_aut_ptr& haut, - const spot::const_twa_graph_ptr& aut, - spot::formula f, - const char* filename, int loc, double run_time, - const char* csv_prefix, const char* csv_suffix) + const spot::const_twa_graph_ptr& aut, + spot::formula f, + const char* filename, int loc, double run_time, + const char* csv_prefix, const char* csv_suffix) { filename_ = filename ? filename : ""; csv_prefix_ = csv_prefix ? csv_prefix : ""; csv_suffix_ = csv_suffix ? csv_suffix : ""; if (loc >= 0 && has('L')) { - std::ostringstream os; - os << loc; - location_ = os.str(); + std::ostringstream os; + os << loc; + location_ = os.str(); } if (haut) { - if (loc < 0 && has('L')) - { - std::ostringstream os; - os << haut->loc; - location_ = os.str(); - } + if (loc < 0 && has('L')) + { + std::ostringstream os; + os << haut->loc; + location_ = os.str(); + } - if (has('T')) - { - spot::twa_sub_statistics s = sub_stats_reachable(haut->aut); - haut_states_ = s.states; - haut_edges_ = s.edges; - haut_trans_ = s.transitions; - } - else if (has('E')) - { - spot::twa_sub_statistics s = sub_stats_reachable(haut->aut); - haut_states_ = s.states; - haut_edges_ = s.edges; - } - if (has('M')) - { - auto n = haut->aut->get_named_prop("automaton-name"); - if (n) - haut_name_ = *n; - else - haut_name_.val().clear(); - } - if (has('S')) - haut_states_ = haut->aut->num_states(); + if (has('T')) + { + spot::twa_sub_statistics s = sub_stats_reachable(haut->aut); + haut_states_ = s.states; + haut_edges_ = s.edges; + haut_trans_ = s.transitions; + } + else if (has('E')) + { + spot::twa_sub_statistics s = sub_stats_reachable(haut->aut); + haut_states_ = s.states; + haut_edges_ = s.edges; + } + if (has('M')) + { + auto n = haut->aut->get_named_prop("automaton-name"); + if (n) + haut_name_ = *n; + else + haut_name_.val().clear(); + } + if (has('S')) + haut_states_ = haut->aut->num_states(); - if (has('A')) - haut_acc_ = haut->aut->acc().num_sets(); + if (has('A')) + haut_acc_ = haut->aut->acc().num_sets(); - if (has('C')) - haut_scc_ = spot::scc_info(haut->aut).scc_count(); + if (has('C')) + haut_scc_ = spot::scc_info(haut->aut).scc_count(); - if (has('G')) - { - std::ostringstream os; - os << haut->aut->get_acceptance(); - haut_gen_acc_ = os.str(); - } + if (has('G')) + { + std::ostringstream os; + os << haut->aut->get_acceptance(); + haut_gen_acc_ = os.str(); + } } if (has('m')) - { - auto n = aut->get_named_prop("automaton-name"); - if (n) - aut_name_ = *n; - else - aut_name_.val().clear(); - } + { + auto n = aut->get_named_prop("automaton-name"); + if (n) + aut_name_ = *n; + else + aut_name_.val().clear(); + } if (has('w')) - { - auto res = spot::couvreur99(aut)->check(); - if (res) - { - auto run = res->accepting_run(); - assert(run); - spot::twa_word w(run->reduce()); - w.simplify(); - std::ostringstream out; - out << w; - aut_word_ = out.str(); - } - else - { - aut_word_.val().clear(); - } - } + { + auto res = spot::couvreur99(aut)->check(); + if (res) + { + auto run = res->accepting_run(); + assert(run); + spot::twa_word w(run->reduce()); + w.simplify(); + std::ostringstream out; + out << w; + aut_word_ = out.str(); + } + else + { + aut_word_.val().clear(); + } + } return this->spot::stat_printer::print(aut, f, run_time); } @@ -230,15 +230,15 @@ public: void print(const spot::twa_graph_ptr& aut, - spot::formula f = nullptr, - // Input location for errors and statistics. - const char* filename = nullptr, - int loc = -1, - // Time and input automaton for statistics - double time = 0.0, - const spot::const_parsed_aut_ptr& haut = nullptr, - const char* csv_prefix = nullptr, - const char* csv_suffix = nullptr); + spot::formula f = nullptr, + // Input location for errors and statistics. + const char* filename = nullptr, + int loc = -1, + // Time and input automaton for statistics + double time = 0.0, + const spot::const_parsed_aut_ptr& haut = nullptr, + const char* csv_prefix = nullptr, + const char* csv_suffix = nullptr); void add_stat(char c, const spot::printable* p); }; diff --git a/bin/common_finput.cc b/bin/common_finput.cc index adf377625..599d0c394 100644 --- a/bin/common_finput.cc +++ b/bin/common_finput.cc @@ -49,8 +49,8 @@ static const argp_option options[] = }; const struct argp finput_argp = { options, parse_opt_finput, - nullptr, nullptr, nullptr, - nullptr, nullptr }; + nullptr, nullptr, nullptr, + nullptr, nullptr }; int parse_opt_finput(int key, char* arg, struct argp_state*) @@ -105,15 +105,15 @@ job_processor::~job_processor() int job_processor::process_string(const std::string& input, - const char* filename, - int linenum) + const char* filename, + int linenum) { auto pf = parse_formula(input); if (!pf.f || !pf.errors.empty()) { if (filename) - error_at_line(0, 0, filename, linenum, "parse error:"); + error_at_line(0, 0, filename, linenum, "parse error:"); pf.format_errors(std::cerr); return 1; } @@ -122,7 +122,7 @@ job_processor::process_string(const std::string& input, int job_processor::process_stream(std::istream& is, - const char* filename) + const char* filename) { int error = 0; int linenum = 1; @@ -141,148 +141,148 @@ job_processor::process_stream(std::istream& is, while (!abort_run && std::getline(is, line)) if (!line.empty()) { - if (col_to_read == 0) - { - error |= process_string(line, filename, linenum++); - } - else // We are reading column COL_TO_READ in a CSV file. - { - // If the line we have read contains an odd number - // of double-quotes, then it is an incomplete CSV line - // that should be completed by the next lines. - unsigned dquotes = 0; - std::string fullline; - unsigned csvlines = 0; - do - { - ++csvlines; - size_t s = line.size(); - for (unsigned i = 0; i < s; ++i) - dquotes += line[i] == '"'; - if (fullline.empty()) - fullline = line; - else - (fullline += '\n') += line; - if (!(dquotes &= 1)) - break; - } - while (std::getline(is, line)); - if (dquotes) - error_at_line(2, errno, filename, linenum, - "mismatched double-quote, " - "reached EOF while parsing this line"); + if (col_to_read == 0) + { + error |= process_string(line, filename, linenum++); + } + else // We are reading column COL_TO_READ in a CSV file. + { + // If the line we have read contains an odd number + // of double-quotes, then it is an incomplete CSV line + // that should be completed by the next lines. + unsigned dquotes = 0; + std::string fullline; + unsigned csvlines = 0; + do + { + ++csvlines; + size_t s = line.size(); + for (unsigned i = 0; i < s; ++i) + dquotes += line[i] == '"'; + if (fullline.empty()) + fullline = line; + else + (fullline += '\n') += line; + if (!(dquotes &= 1)) + break; + } + while (std::getline(is, line)); + if (dquotes) + error_at_line(2, errno, filename, linenum, + "mismatched double-quote, " + "reached EOF while parsing this line"); - // Now that we have a full CSV line, extract the right - // column. + // Now that we have a full CSV line, extract the right + // column. - const char* str = fullline.c_str(); - const char* col1_start = str; - // Delimiters for the extracted column. - const char* coln_start = str; - const char* coln_end = nullptr; - // The current column. (1-based) - int colnum = 1; - // Whether we are parsing a double-quoted string. - bool instring = false; - // Note that RFC 4180 has strict rules about - // double-quotes: ① if a field is double-quoted, the first - // and last characters of the field should be - // double-quotes; ② if a field contains a double-quote - // then it should be double quoted, and the occurrences - // of double-quotes should be doubled. Therefore a CSV file - // may no contain a line such as: - // foo,bar"ba""z",12 - // Tools have different interpretation of such a line. - // For instance Python's pandas.read_csv() function will - // load the second field verbatim as the string 'bar"ba""z"', - // while R's read.csv() function will load it as the - // string 'barba"z'. We use this second interpretation, because - // it also makes it possible to parse CSVs fields formatted - // with leading spaces (often for cosmetic purpose). When - // extracting the second field of - // foo, "ba""z", 12 - // we will return ' baz' and the leading space will be ignored - // by our LTL formula parser. - while (*str) - { - switch (*str) - { - case '"': - // Doubled double-quotes are used to escape - // double-quotes. - if (instring && str[1] == '"') - ++str; - else - instring = !instring; - break; - case ',': - if (!instring) - { - if (col_to_read == colnum) - coln_end = str; - ++colnum; - if (col_to_read == colnum) - coln_start = str + 1; - } - break; - } - // Once we have the end delimiter for our target - // column, we have all we need. - if (coln_end) - break; - ++str; - } - if (!*str) - { - if (colnum != col_to_read) - // Skip this line as it has no enough columns. - continue; - else - // The target columns ends at the end of the line. - coln_end = str; - } + const char* str = fullline.c_str(); + const char* col1_start = str; + // Delimiters for the extracted column. + const char* coln_start = str; + const char* coln_end = nullptr; + // The current column. (1-based) + int colnum = 1; + // Whether we are parsing a double-quoted string. + bool instring = false; + // Note that RFC 4180 has strict rules about + // double-quotes: ① if a field is double-quoted, the first + // and last characters of the field should be + // double-quotes; ② if a field contains a double-quote + // then it should be double quoted, and the occurrences + // of double-quotes should be doubled. Therefore a CSV file + // may no contain a line such as: + // foo,bar"ba""z",12 + // Tools have different interpretation of such a line. + // For instance Python's pandas.read_csv() function will + // load the second field verbatim as the string 'bar"ba""z"', + // while R's read.csv() function will load it as the + // string 'barba"z'. We use this second interpretation, because + // it also makes it possible to parse CSVs fields formatted + // with leading spaces (often for cosmetic purpose). When + // extracting the second field of + // foo, "ba""z", 12 + // we will return ' baz' and the leading space will be ignored + // by our LTL formula parser. + while (*str) + { + switch (*str) + { + case '"': + // Doubled double-quotes are used to escape + // double-quotes. + if (instring && str[1] == '"') + ++str; + else + instring = !instring; + break; + case ',': + if (!instring) + { + if (col_to_read == colnum) + coln_end = str; + ++colnum; + if (col_to_read == colnum) + coln_start = str + 1; + } + break; + } + // Once we have the end delimiter for our target + // column, we have all we need. + if (coln_end) + break; + ++str; + } + if (!*str) + { + if (colnum != col_to_read) + // Skip this line as it has no enough columns. + continue; + else + // The target columns ends at the end of the line. + coln_end = str; + } - // Skip the line if it has an empty field. - if (coln_start == coln_end) - continue; + // Skip the line if it has an empty field. + if (coln_start == coln_end) + continue; - // save the contents before and after that columns for the - // %< and %> escapes (ignoring the trailing and leading - // commas). - prefix = (col_to_read != 1) ? - strndup(col1_start, coln_start - col1_start - 1) : nullptr; - suffix = (*coln_end != 0) ? strdup(coln_end + 1) : nullptr; - std::string field(coln_start, coln_end); - // Remove double-quotes if any. - if (field.find('"') != std::string::npos) - { - unsigned dst = 0; - bool instring = false; - for (; coln_start != coln_end; ++coln_start) - if (*coln_start == '"') - // A doubled double-quote instead a double-quoted - // string is an escaped double-quote. - if (instring && coln_start[1] == '"') - field[dst++] = *++coln_start; - else - instring = !instring; - else - field[dst++] = *coln_start; - field.resize(dst); - } - error |= process_string(field, filename, linenum); - linenum += csvlines; - if (prefix) - { - free(prefix); - prefix = nullptr; - } - if (suffix) - { - free(suffix); - suffix = nullptr; - } - } + // save the contents before and after that columns for the + // %< and %> escapes (ignoring the trailing and leading + // commas). + prefix = (col_to_read != 1) ? + strndup(col1_start, coln_start - col1_start - 1) : nullptr; + suffix = (*coln_end != 0) ? strdup(coln_end + 1) : nullptr; + std::string field(coln_start, coln_end); + // Remove double-quotes if any. + if (field.find('"') != std::string::npos) + { + unsigned dst = 0; + bool instring = false; + for (; coln_start != coln_end; ++coln_start) + if (*coln_start == '"') + // A doubled double-quote instead a double-quoted + // string is an escaped double-quote. + if (instring && coln_start[1] == '"') + field[dst++] = *++coln_start; + else + instring = !instring; + else + field[dst++] = *coln_start; + field.resize(dst); + } + error |= process_string(field, filename, linenum); + linenum += csvlines; + if (prefix) + { + free(prefix); + prefix = nullptr; + } + if (suffix) + { + free(suffix); + suffix = nullptr; + } + } } return error; } @@ -315,23 +315,23 @@ job_processor::process_file(const char* filename) long int col = strtol(slash + 1, &end, 10); // strtol ate all remaining characters and NN is positive if (errno == 0 && !*end && col != 0) - { - col_to_read = col; - if (real_filename) - free(real_filename); - real_filename = strndup(filename, slash - filename); + { + col_to_read = col; + if (real_filename) + free(real_filename); + real_filename = strndup(filename, slash - filename); - // Special case for stdin. - if (real_filename[0] == '-' && real_filename[1] == 0) - return process_stream(std::cin, real_filename); + // Special case for stdin. + if (real_filename[0] == '-' && real_filename[1] == 0) + return process_stream(std::cin, real_filename); - std::ifstream input(real_filename); - if (input) - return process_stream(input, real_filename); + std::ifstream input(real_filename); + if (input) + return process_stream(input, real_filename); - error(2, errno, "cannot open '%s' nor '%s'", - filename, real_filename); - } + error(2, errno, "cannot open '%s' nor '%s'", + filename, real_filename); + } } error(2, saved_errno, "cannot open '%s'", filename); @@ -345,11 +345,11 @@ job_processor::run() for (auto& j: jobs) { if (!j.file_p) - error |= process_string(j.str); + error |= process_string(j.str); else - error |= process_file(j.str); + error |= process_file(j.str); if (abort_run) - break; + break; } return error; } diff --git a/bin/common_finput.hh b/bin/common_finput.hh index 71a7ceb14..0c4b3d459 100644 --- a/bin/common_finput.hh +++ b/bin/common_finput.hh @@ -28,7 +28,7 @@ struct job { const char* str; - bool file_p; // true if str is a filename, false if it is a formula + bool file_p; // true if str is a filename, false if it is a formula job(const char* str, bool file_p) : str(str), file_p(file_p) @@ -58,11 +58,11 @@ public: virtual int process_formula(spot::formula f, - const char* filename = nullptr, int linenum = 0) = 0; + const char* filename = nullptr, int linenum = 0) = 0; virtual int process_string(const std::string& str, - const char* filename = nullptr, int linenum = 0); + const char* filename = nullptr, int linenum = 0); virtual int process_stream(std::istream& is, const char* filename); diff --git a/bin/common_hoaread.cc b/bin/common_hoaread.cc index 2d19227b5..809796b0c 100644 --- a/bin/common_hoaread.cc +++ b/bin/common_hoaread.cc @@ -41,8 +41,8 @@ spot::twa_graph_ptr read_automaton(const char* filename, spot::bdd_dict_ptr& dict) { auto p = spot::parse_aut(filename, dict, - spot::default_environment::instance(), - opt_parse); + spot::default_environment::instance(), + opt_parse); if (p->format_errors(std::cerr)) error(2, 0, "failed to read automaton from %s", filename); if (p->aborted) @@ -86,5 +86,5 @@ parse_opt_hoaread(int key, char* arg, struct argp_state*) const struct argp hoaread_argp = { options, parse_opt_hoaread, - nullptr, nullptr, nullptr, - nullptr, nullptr }; + nullptr, nullptr, nullptr, + nullptr, nullptr }; diff --git a/bin/common_output.cc b/bin/common_output.cc index 9cee42349..54cf2badf 100644 --- a/bin/common_output.cc +++ b/bin/common_output.cc @@ -65,13 +65,13 @@ static const argp_option options[] = }; const struct argp output_argp = { options, parse_opt_output, - nullptr, nullptr, nullptr, - nullptr, nullptr }; + nullptr, nullptr, nullptr, + nullptr, nullptr }; static void report_not_ltl(spot::formula f, - const char* filename, int linenum, const char* syn) + const char* filename, int linenum, const char* syn) { std::string s = spot::str_psl(f); static const char msg[] = @@ -84,30 +84,30 @@ report_not_ltl(spot::formula f, std::ostream& stream_formula(std::ostream& out, - spot::formula f, const char* filename, int linenum) + spot::formula f, const char* filename, int linenum) { switch (output_format) { case lbt_output: if (f.is_ltl_formula()) - spot::print_lbt_ltl(out, f); + spot::print_lbt_ltl(out, f); else - report_not_ltl(f, filename, linenum, "LBT"); + report_not_ltl(f, filename, linenum, "LBT"); break; case spot_output: spot::print_psl(out, f, full_parenth); break; case spin_output: if (f.is_ltl_formula()) - spot::print_spin_ltl(out, f, full_parenth); + spot::print_spin_ltl(out, f, full_parenth); else - report_not_ltl(f, filename, linenum, "Spin"); + report_not_ltl(f, filename, linenum, "Spin"); break; case wring_output: if (f.is_ltl_formula()) - spot::print_wring_ltl(out, f); + spot::print_wring_ltl(out, f); else - report_not_ltl(f, filename, linenum, "Wring"); + report_not_ltl(f, filename, linenum, "Wring"); break; case utf8_output: spot::print_utf8_psl(out, f, full_parenth); @@ -124,8 +124,8 @@ stream_formula(std::ostream& out, static void stream_escapable_formula(std::ostream& os, - spot::formula f, - const char* filename, int linenum) + spot::formula f, + const char* filename, int linenum) { if (escape_csv) { @@ -260,17 +260,17 @@ parse_opt_output(int key, char* arg, struct argp_state*) static void output_formula(std::ostream& out, - spot::formula f, - const char* filename = nullptr, int linenum = 0, - const char* prefix = nullptr, const char* suffix = nullptr) + spot::formula f, + const char* filename = nullptr, int linenum = 0, + const char* prefix = nullptr, const char* suffix = nullptr) { if (!format) { if (prefix) - out << prefix << ','; + out << prefix << ','; stream_escapable_formula(out, f, filename, linenum); if (suffix) - out << ',' << suffix; + out << ',' << suffix; } else { @@ -287,14 +287,14 @@ void void output_formula_checked(spot::formula f, - const char* filename, int linenum, - const char* prefix, const char* suffix) + const char* filename, int linenum, + const char* prefix, const char* suffix) { if (output_format == count_output) { if (outputnamer) - throw std::runtime_error - ("options --output and --count are incompatible"); + throw std::runtime_error + ("options --output and --count are incompatible"); return; } if (output_format == quiet_output) @@ -308,7 +308,7 @@ output_formula_checked(spot::formula f, std::string fname = outputname.str(); auto p = outputfiles.emplace(fname, nullptr); if (p.second) - p.first->second.reset(new output_file(fname.c_str())); + p.first->second.reset(new output_file(fname.c_str())); out = &p.first->second->ostream(); } output_formula(*out, f, filename, linenum, prefix, suffix); diff --git a/bin/common_output.hh b/bin/common_output.hh index ebc93dcf0..7b40db048 100644 --- a/bin/common_output.hh +++ b/bin/common_output.hh @@ -30,7 +30,7 @@ #include "common_file.hh" enum output_format_t { spot_output, spin_output, utf8_output, - lbt_output, wring_output, latex_output, + lbt_output, wring_output, latex_output, quiet_output, count_output }; extern output_format_t output_format; extern bool full_parenth; @@ -43,12 +43,12 @@ int parse_opt_output(int key, char* arg, struct argp_state* state); // Low-level output std::ostream& stream_formula(std::ostream& out, - spot::formula f, const char* filename, int linenum); + spot::formula f, const char* filename, int linenum); void output_formula_checked(spot::formula f, - const char* filename = nullptr, int linenum = 0, - const char* prefix = nullptr, - const char* suffix = nullptr); + const char* filename = nullptr, int linenum = 0, + const char* prefix = nullptr, + const char* suffix = nullptr); class printable_formula: @@ -72,15 +72,15 @@ public: aut_stat_printer(std::ostream& os, const char* format) : spot::stat_printer(os, format) { - declare('f', &formula_); // Override the formula printer. + declare('f', &formula_); // Override the formula printer. } using spot::formater::set_output; std::ostream& print(const spot::const_twa_graph_ptr& aut, - spot::formula f = nullptr, - double run_time = -1.) + spot::formula f = nullptr, + double run_time = -1.) { formula_ = f; return this->spot::stat_printer::print(aut, f, run_time); diff --git a/bin/common_post.cc b/bin/common_post.cc index bb751835d..5679f542c 100644 --- a/bin/common_post.cc +++ b/bin/common_post.cc @@ -155,7 +155,7 @@ parse_opt_post(int key, char*, struct argp_state*) break; case OPT_TGBA: if (automaton_format == Spin) - error(2, 0, "--spin and --tgba are incompatible"); + error(2, 0, "--spin and --tgba are incompatible"); type = spot::postprocessor::TGBA; break; default: @@ -165,7 +165,7 @@ parse_opt_post(int key, char*, struct argp_state*) } const struct argp post_argp = { options, parse_opt_post, - nullptr, nullptr, nullptr, nullptr, nullptr }; + nullptr, nullptr, nullptr, nullptr, nullptr }; const struct argp post_argp_disabled = { options_disabled, parse_opt_post, - nullptr, nullptr, nullptr, - nullptr, nullptr }; + nullptr, nullptr, nullptr, + nullptr, nullptr }; diff --git a/bin/common_post.hh b/bin/common_post.hh index 8e219bfc0..faaa1fa61 100644 --- a/bin/common_post.hh +++ b/bin/common_post.hh @@ -23,7 +23,7 @@ #include #include -extern const struct argp post_argp; // postprocessing enabled +extern const struct argp post_argp; // postprocessing enabled extern const struct argp post_argp_disabled; // postprocessing disabled extern spot::postprocessor::output_type type; diff --git a/bin/common_r.hh b/bin/common_r.hh index 9a36c104a..add0ddb91 100644 --- a/bin/common_r.hh +++ b/bin/common_r.hh @@ -24,21 +24,21 @@ #define OPT_R 'r' -#define DECLARE_OPT_R \ - { "simplify", OPT_R, "LEVEL", OPTION_ARG_OPTIONAL, \ - "simplify formulas according to LEVEL (see below); LEVEL is " \ +#define DECLARE_OPT_R \ + { "simplify", OPT_R, "LEVEL", OPTION_ARG_OPTIONAL, \ + "simplify formulas according to LEVEL (see below); LEVEL is " \ "set to 3 if omitted", 0 } -#define LEVEL_DOC(g) \ - { nullptr, 0, nullptr, 0, \ - "The simplification LEVEL may be set as follows.", g }, \ - { " 0", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ - "No rewriting", 0 }, \ - { " 1", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ - "basic rewritings and eventual/universal rules", 0 }, \ - { " 2", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ - "additional syntactic implication rules", 0 }, \ - { " 3", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ +#define LEVEL_DOC(g) \ + { nullptr, 0, nullptr, 0, \ + "The simplification LEVEL may be set as follows.", g }, \ + { " 0", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ + "No rewriting", 0 }, \ + { " 1", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ + "basic rewritings and eventual/universal rules", 0 }, \ + { " 2", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ + "additional syntactic implication rules", 0 }, \ + { " 3", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ "better implications using containment", 0 } extern int simplification_level; diff --git a/bin/common_range.cc b/bin/common_range.cc index fd338f082..44121e685 100644 --- a/bin/common_range.cc +++ b/bin/common_range.cc @@ -42,7 +42,7 @@ parse_range(const char* str, int missing_left, int missing_right) // No leading number. It's OK as long as the string is not // empty. if (!*end) - error(1, 0, "invalid empty range"); + error(1, 0, "invalid empty range"); res.min = missing_left; } if (!*end) @@ -54,24 +54,24 @@ parse_range(const char* str, int missing_left, int missing_right) { // Skip : or .. if (end[0] == ':') - ++end; + ++end; else if (end[0] == '.' && end[1] == '.') - end += 2; + end += 2; if (!*end && missing_right != 0) - { - res.max = missing_right; - } + { + res.max = missing_right; + } else - { - // Parse the next integer. - char* end2; - res.max = strtol(end, &end2, 10); - if (end == end2) - error(1, 0, "invalid range '%s' (missing end?)", str); - if (*end2) - error(1, 0, "invalid range '%s' (trailing garbage?)", str); - } + { + // Parse the next integer. + char* end2; + res.max = strtol(end, &end2, 10); + if (end == end2) + error(1, 0, "invalid range '%s' (missing end?)", str); + if (*end2) + error(1, 0, "invalid range '%s' (trailing garbage?)", str); + } } if (res.min < 0 || res.max < 0) diff --git a/bin/common_range.hh b/bin/common_range.hh index 101db4537..0fae93aa6 100644 --- a/bin/common_range.hh +++ b/bin/common_range.hh @@ -19,15 +19,15 @@ #pragma once -#define RANGE_DOC \ - { nullptr, 0, nullptr, 0, \ - "RANGE may have one of the following forms: 'INT', " \ +#define RANGE_DOC \ + { nullptr, 0, nullptr, 0, \ + "RANGE may have one of the following forms: 'INT', " \ "'INT..INT', or '..INT'.\nIn the latter case, the missing number " \ "is assumed to be 1.", 0 } -#define RANGE_DOC_FULL \ - { nullptr, 0, nullptr, 0, \ - "RANGE may have one of the following forms: 'INT', " \ +#define RANGE_DOC_FULL \ + { nullptr, 0, nullptr, 0, \ + "RANGE may have one of the following forms: 'INT', " \ "'INT..INT', '..INT', or 'INT..'", 0 } struct range @@ -47,4 +47,4 @@ struct range // values. Additionally, if missing_right == 0, then the INT.. form // is disallowed. range parse_range(const char* str, - int missing_left = 1, int missing_right = 0); + int missing_left = 1, int missing_right = 0); diff --git a/bin/common_setup.cc b/bin/common_setup.cc index 6eb0d34a0..150375d9d 100644 --- a/bin/common_setup.cc +++ b/bin/common_setup.cc @@ -129,7 +129,7 @@ parse_opt_misc(int key, char*, struct argp_state* state) break; case OPT_USAGE: argp_state_help(state, state->out_stream, - ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); + ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); break; case OPT_VERSION: display_version(state->out_stream, state); @@ -143,8 +143,8 @@ parse_opt_misc(int key, char*, struct argp_state* state) const struct argp misc_argp = { options, parse_opt_misc, - nullptr, nullptr, nullptr, nullptr, nullptr }; + nullptr, nullptr, nullptr, nullptr, nullptr }; const struct argp misc_argp_hidden = { options_hidden, parse_opt_misc, - nullptr, nullptr, nullptr, - nullptr, nullptr }; + nullptr, nullptr, nullptr, + nullptr, nullptr }; diff --git a/bin/common_trans.cc b/bin/common_trans.cc index 5c5ec3332..bec70a850 100644 --- a/bin/common_trans.cc +++ b/bin/common_trans.cc @@ -53,17 +53,17 @@ static void show_shorthands() { std::cout << ("If a COMMANDFMT does not use any %-sequence, and starts with one of\n" - "the following words, then the string on the right is appended.\n\n"); + "the following words, then the string on the right is appended.\n\n"); for (auto& s: shorthands) std::cout << " " - << std::left << std::setw(12) << s.prefix - << s.suffix << '\n'; + << std::left << std::setw(12) << s.prefix + << s.suffix << '\n'; std::cout << ("\nAny {name} and directory component is skipped for the purpose of\n" - "matching those prefixes. So for instance\n" - " '{DRA} ~/mytools/ltl2dstar-0.5.2'\n" - "will changed into\n" - " '{DRA} ~/mytools/ltl2dstar-0.5.2 --output-format=hoa %L %O'\n"); + "matching those prefixes. So for instance\n" + " '{DRA} ~/mytools/ltl2dstar-0.5.2'\n" + "will changed into\n" + " '{DRA} ~/mytools/ltl2dstar-0.5.2 --output-format=hoa %L %O'\n"); } @@ -76,19 +76,19 @@ translator_spec::translator_spec(const char* spec) const char* pos = cmd; unsigned count = 1; while (*++pos) - { - if (*pos == '{') - ++count; - else if (*pos == '}') - if (!--count) - { - name = strndup(cmd + 1, pos - cmd - 1); - cmd = pos + 1; - while (*cmd == ' ' || *cmd == '\t') - ++cmd; - break; - } - } + { + if (*pos == '{') + ++count; + else if (*pos == '}') + if (!--count) + { + name = strndup(cmd + 1, pos - cmd - 1); + cmd = pos + 1; + while (*cmd == ' ' || *cmd == '\t') + ++cmd; + break; + } + } } // If there is no % in the string, look for a known // command from our shorthand list. If we find it, @@ -100,29 +100,29 @@ translator_spec::translator_spec(const char* spec) auto basename = cmd; auto pos = cmd; while (*pos) - { - if (*pos == '/') - basename = pos + 1; - else if (*pos == ' ') - break; - ++pos; - } + { + if (*pos == '/') + basename = pos + 1; + else if (*pos == ' ') + break; + ++pos; + } // Match a shorthand. for (auto& p: shorthands) - { - int n = strlen(p.prefix); - if (strncmp(basename, p.prefix, n) == 0) - { - int m = strlen(p.suffix); - int q = strlen(cmd); - char* tmp = static_cast(malloc(q + m + 1)); - strcpy(tmp, cmd); - strcpy(tmp + q, p.suffix); - cmd = tmp; - allocated = true; - break; - } - } + { + int n = strlen(p.prefix); + if (strncmp(basename, p.prefix, n) == 0) + { + int m = strlen(p.suffix); + int q = strlen(cmd); + char* tmp = static_cast(malloc(q + m + 1)); + strcpy(tmp, cmd); + strcpy(tmp + q, p.suffix); + cmd = tmp; + allocated = true; + break; + } + } } if (!allocated) cmd = strdup(cmd); @@ -186,7 +186,7 @@ printable_result_filename::print(std::ostream& os, const char*) const translator_runner::translator_runner(spot::bdd_dict_ptr dict, - bool no_output_allowed) + bool no_output_allowed) : dict(dict) { declare('f', &string_ltl_spot); @@ -213,17 +213,17 @@ translator_runner::translator_runner(spot::bdd_dict_ptr dict, const translator_spec& t = translators[n]; scan(t.cmd, has); if (!(has['f'] || has['s'] || has['l'] || has['w'] - || has['F'] || has['S'] || has['L'] || has['W'])) - error(2, 0, "no input %%-sequence in '%s'.\n Use " - "one of %%f,%%s,%%l,%%w,%%F,%%S,%%L,%%W to indicate how " - "to pass the formula.", t.spec); + || has['F'] || has['S'] || has['L'] || has['W'])) + error(2, 0, "no input %%-sequence in '%s'.\n Use " + "one of %%f,%%s,%%l,%%w,%%F,%%S,%%L,%%W to indicate how " + "to pass the formula.", t.spec); if (!no_output_allowed - && !(has['O'] || - // backward-compatibility - has['D'] || has['N'] || has['T'] || has['H'])) - error(2, 0, "no output %%-sequence in '%s'.\n Use " - "%%O to indicate where the automaton is output.", - t.spec); + && !(has['O'] || + // backward-compatibility + has['D'] || has['N'] || has['T'] || has['H'])) + error(2, 0, "no output %%-sequence in '%s'.\n Use " + "%%O to indicate where the automaton is output.", + t.spec); // Remember the %-sequences used by all translators. prime(t.cmd); } @@ -231,7 +231,7 @@ translator_runner::translator_runner(spot::bdd_dict_ptr dict, void translator_runner::string_to_tmp(std::string& str, unsigned n, - std::string& tmpname) + std::string& tmpname) { char prefix[30]; snprintf(prefix, sizeof prefix, "lcr-i%u-", n); @@ -302,18 +302,18 @@ sig_handler(int sig) { timed_out = true; if (--alarm_on) - { - // Send SIGTERM to children. - kill(-child_pid, SIGTERM); - // Try again later if it didn't work. (alarm() will be reset - // if it did work and the call to wait() returns) - alarm(2); - } + { + // Send SIGTERM to children. + kill(-child_pid, SIGTERM); + // Try again later if it didn't work. (alarm() will be reset + // if it did work and the call to wait() returns) + alarm(2); + } else - { - // After a few gentle tries, really kill that child. - kill(-child_pid, SIGKILL); - } + { + // After a few gentle tries, really kill that child. + kill(-child_pid, SIGKILL); + } } else { @@ -370,7 +370,7 @@ exec_with_timeout(const char* cmd) alarm_on = 0; if (w == -1) - error(2, errno, "error during wait()"); + error(2, errno, "error during wait()"); alarm(0); } @@ -424,7 +424,7 @@ static int parse_opt_trans(int key, char* arg, struct argp_state*) timeout = to_pos_int(arg); #if !ENABLE_TIMEOUT std::cerr << "warning: setting a timeout is not supported " - << "on your platform" << std::endl; + << "on your platform" << std::endl; #endif break; case OPT_LIST: @@ -437,4 +437,4 @@ static int parse_opt_trans(int key, char* arg, struct argp_state*) } const struct argp trans_argp = { options, parse_opt_trans, nullptr, nullptr, - nullptr, nullptr, nullptr }; + nullptr, nullptr, nullptr }; diff --git a/bin/common_trans.hh b/bin/common_trans.hh index a14be1782..473f859a5 100644 --- a/bin/common_trans.hh +++ b/bin/common_trans.hh @@ -89,9 +89,9 @@ public: using spot::formater::has; translator_runner(spot::bdd_dict_ptr dict, - // whether we accept the absence of output - // specifier - bool no_output_allowed = false); + // whether we accept the absence of output + // specifier + bool no_output_allowed = false); void string_to_tmp(std::string& str, unsigned n, std::string& tmpname); const std::string& formula() const; void round_formula(spot::formula f, unsigned serial); diff --git a/bin/dstar2tgba.cc b/bin/dstar2tgba.cc index c7ab6b6c2..4ce7c8031 100644 --- a/bin/dstar2tgba.cc +++ b/bin/dstar2tgba.cc @@ -89,9 +89,9 @@ parse_opt(int key, char* arg, struct argp_state*) break; case 'x': { - const char* opt = extra_options.parse_options(arg); - if (opt) - error(2, 0, "failed to parse --options near '%s'", opt); + const char* opt = extra_options.parse_options(arg); + if (opt) + error(2, 0, "failed to parse --options near '%s'", opt); } break; case ARGP_KEY_ARG: @@ -125,7 +125,7 @@ namespace int process_automaton(const spot::const_parsed_aut_ptr& haut, - const char* filename) + const char* filename) { spot::stopwatch sw; sw.start(); @@ -151,19 +151,19 @@ namespace auto hp = spot::automaton_stream_parser(filename, opt_parse); int err = 0; while (!abort_run) - { - auto haut = hp.parse(spot::make_bdd_dict()); - if (!haut->aut && haut->errors.empty()) - break; - if (haut->format_errors(std::cerr)) - err = 2; - if (!haut->aut) - error(2, 0, "failed to read automaton from %s", filename); - else if (haut->aborted) - err = std::max(err, aborted(haut, filename)); - else + { + auto haut = hp.parse(spot::make_bdd_dict()); + if (!haut->aut && haut->errors.empty()) + break; + if (haut->format_errors(std::cerr)) + err = 2; + if (!haut->aut) + error(2, 0, "failed to read automaton from %s", filename); + else if (haut->aborted) + err = std::max(err, aborted(haut, filename)); + else process_automaton(haut, filename); - } + } return err; } }; @@ -175,7 +175,7 @@ main(int argc, char** argv) setup(argv); const argp ap = { options, parse_opt, "[FILENAMES...]", - argp_program_doc, children, nullptr, nullptr }; + argp_program_doc, children, nullptr, nullptr }; if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) exit(err); @@ -192,7 +192,7 @@ main(int argc, char** argv) { dstar_processor processor(post); if (processor.run()) - return 2; + return 2; } catch (const std::runtime_error& e) { diff --git a/bin/genltl.cc b/bin/genltl.cc index 94eb75cd1..39a5a269c 100644 --- a/bin/genltl.cc +++ b/bin/genltl.cc @@ -43,8 +43,8 @@ // @InProceedings{gastin.01.cav, // author = {Paul Gastin and Denis Oddoux}, // title = {Fast {LTL} to {B\"u}chi Automata Translation}, -// booktitle = {Proceedings of the 13th International Conference on -// Computer Aided Verification (CAV'01)}, +// booktitle = {Proceedings of the 13th International Conference on +// Computer Aided Verification (CAV'01)}, // pages = {53--65}, // year = 2001, // editor = {G. Berry and H. Comon and A. Finkel}, @@ -58,7 +58,7 @@ // author = {Kristin Y. Rozier and Moshe Y. Vardi}, // title = {LTL Satisfiability Checking}, // booktitle = {Proceedings of the 12th International SPIN Workshop on -// Model Checking of Software (SPIN'07)}, +// Model Checking of Software (SPIN'07)}, // pages = {149--167}, // year = {2007}, // volume = {4595}, @@ -294,9 +294,9 @@ E_n(std::string name, int n) p << name << n; formula f = formula::ap(p.str()); if (result) - result = And_(f, result); + result = And_(f, result); else - result = f; + result = f; result = F_(result); } return result; @@ -314,9 +314,9 @@ phi_n(std::string name, int n) for (; n > 0; --n) { if (result) - result = And_(p, X_(result)); + result = And_(p, X_(result)); else - result = p; + result = p; } return result; } @@ -339,14 +339,14 @@ phi_prime_n(std::string name, int n) for (; n > 0; --n) { if (result) - { - p = X_(p); - result = And_(result, p); - } + { + p = X_(p); + result = And_(result, p); + } else - { - result = p; - } + { + result = p; + } } return result; } @@ -377,9 +377,9 @@ GF_n(std::string name, int n, bool conj = true) formula f = G_(F_(formula::ap(p.str()))); if (result) - result = formula::multop(o, {f, result}); + result = formula::multop(o, {f, result}); else - result = f; + result = f; } return result; } @@ -403,9 +403,9 @@ FG_n(std::string name, int n, bool conj = false) formula f = F_(G_(formula::ap(p.str()))); if (result) - result = formula::multop(o, {f, result}); + result = formula::multop(o, {f, result}); else - result = f; + result = f; } return result; } @@ -426,11 +426,11 @@ bin_n(std::string name, int n, op o, bool right_assoc = false) p << name << (right_assoc ? (n + 1 - i) : i); formula f = formula::ap(p.str()); if (!result) - result = f; + result = f; else if (right_assoc) - result = formula::binop(o, f, result); + result = formula::binop(o, f, result); else - result = formula::binop(o, result, f); + result = formula::binop(o, result, f); } return result; } @@ -464,9 +464,9 @@ R_n(std::string name, int n) formula f = Or_(gf, fg); if (result) - result = And_(f, result); + result = And_(f, result); else - result = f; + result = f; } return result; } @@ -501,9 +501,9 @@ Q_n(std::string name, int n) f = Or_(f, g); if (result) - result = And_(f, result); + result = And_(f, result); else - result = f; + result = f; } return result; } @@ -527,9 +527,9 @@ combunop_n(std::string name, int n, op o, bool conj = false) formula f = formula::unop(o, formula::ap(p.str())); if (result) - result = formula::multop(cop, {f, result}); + result = formula::multop(cop, {f, result}); else - result = f; + result = f; } return result; } @@ -575,7 +575,7 @@ ltl_counter(std::string bit, std::string marker, int n, bool linear) // G(m -> X(!m)&XX(!m)&XXX(m)) [if n = 3] std::vector v(n); for (int i = 0; i + 1 < n; ++i) - v[i] = X_n(neg_m, i + 1); + v[i] = X_n(neg_m, i + 1); v[n - 1] = X_n(m, n); res[0] = And_(m, G_(Implies_(m, formula::And(std::move(v))))); } @@ -584,7 +584,7 @@ ltl_counter(std::string bit, std::string marker, int n, bool linear) // G(m -> X(!m & X(!m X(m)))) [if n = 3] formula p = m; for (int i = n - 1; i > 0; --i) - p = And_(neg_m, X_(p)); + p = And_(neg_m, X_(p)); res[0] = And_(m, G_(Implies_(m, X_(p)))); } @@ -594,7 +594,7 @@ ltl_counter(std::string bit, std::string marker, int n, bool linear) // !b & X(!b) & XX(!b) [if n = 3] std::vector v2(n); for (int i = 0; i < n; ++i) - v2[i] = X_n(neg_b, i); + v2[i] = X_n(neg_b, i); res[1] = formula::And(std::move(v2)); } else @@ -602,7 +602,7 @@ ltl_counter(std::string bit, std::string marker, int n, bool linear) // !b & X(!b & X(!b)) [if n = 3] formula p = neg_b; for (int i = n - 1; i > 0; --i) - p = And_(neg_b, X_(p)); + p = And_(neg_b, X_(p)); res[1] = p; } @@ -613,26 +613,26 @@ ltl_counter(std::string bit, std::string marker, int n, bool linear) formula Xnm1_b = X_n(b, n - 1); formula Xn_b = X_(Xnm1_b); res[2] = G_(Implies_(And_(m, neg_b), - AndX_(Xnm1_b, U_(And_(Not_(m), Equiv_(b, Xn_b)), m)))); + AndX_(Xnm1_b, U_(And_(Not_(m), Equiv_(b, Xn_b)), m)))); // From the least significant bit to the first 0, all the bits // are flipped on the next value. Remaining bits are identical. formula Xnm1_negb = X_n(neg_b, n - 1); formula Xn_negb = X_(Xnm1_negb); res[3] = G_(Implies_(And_(m, b), - AndX_(Xnm1_negb, - U_(And_(And_(b, neg_m), Xn_negb), - Or_(m, And_(And_(neg_m, neg_b), - AndX_(Xnm1_b, - U_(And_(neg_m, - Equiv_(b, Xn_b)), - m)))))))); + AndX_(Xnm1_negb, + U_(And_(And_(b, neg_m), Xn_negb), + Or_(m, And_(And_(neg_m, neg_b), + AndX_(Xnm1_b, + U_(And_(neg_m, + Equiv_(b, Xn_b)), + m)))))))); return formula::And(std::move(res)); } static formula ltl_counter_carry(std::string bit, std::string marker, - std::string carry, int n, bool linear) + std::string carry, int n, bool linear) { formula b = formula::ap(bit); formula neg_b = Not_(b); @@ -650,7 +650,7 @@ ltl_counter_carry(std::string bit, std::string marker, // G(m -> X(!m)&XX(!m)&XXX(m)) [if n = 3] std::vector v(n); for (int i = 0; i + 1 < n; ++i) - v[i] = X_n(neg_m, i + 1); + v[i] = X_n(neg_m, i + 1); v[n - 1] = X_n(m, n); res[0] = And_(m, G_(Implies_(m, formula::And(std::move(v))))); } @@ -659,7 +659,7 @@ ltl_counter_carry(std::string bit, std::string marker, // G(m -> X(!m & X(!m X(m)))) [if n = 3] formula p = m; for (int i = n - 1; i > 0; --i) - p = And_(neg_m, X_(p)); + p = And_(neg_m, X_(p)); res[0] = And_(m, G_(Implies_(m, X_(p)))); } @@ -669,7 +669,7 @@ ltl_counter_carry(std::string bit, std::string marker, // !b & X(!b) & XX(!b) [if n = 3] std::vector v2(n); for (int i = 0; i < n; ++i) - v2[i] = X_n(neg_b, i); + v2[i] = X_n(neg_b, i); res[1] = formula::And(std::move(v2)); } else @@ -677,7 +677,7 @@ ltl_counter_carry(std::string bit, std::string marker, // !b & X(!b & X(!b)) [if n = 3] formula p = neg_b; for (int i = n - 1; i > 0; --i) - p = And_(neg_b, X_(p)); + p = And_(neg_b, X_(p)); res[1] = p; } @@ -694,24 +694,24 @@ ltl_counter_carry(std::string bit, std::string marker, { // If there's no carry, then all of the bits stay the same n steps later. res[4] = G_(Implies_(And_(neg_c, X_(neg_m)), - And_(X_(Not_(c)), Equiv_(X_(b), X_(Xn_b))))); + And_(X_(Not_(c)), Equiv_(X_(b), X_(Xn_b))))); // If there's a carry, then add one: flip the bits of b and // adjust the carry. res[5] = G_(Implies_(c, And_(Implies_(X_(neg_b), - And_(X_(neg_c), X_(Xn_b))), - Implies_(X_(b), - And_(X_(c), X_(Xn_negb)))))); + And_(X_(neg_c), X_(Xn_b))), + Implies_(X_(b), + And_(X_(c), X_(Xn_negb)))))); } else { // If there's no carry, then all of the bits stay the same n steps later. res[4] = G_(Implies_(And_(neg_c, X_(neg_m)), - X_(And_(Not_(c), Equiv_(b, Xn_b))))); + X_(And_(Not_(c), Equiv_(b, Xn_b))))); // If there's a carry, then add one: flip the bits of b and // adjust the carry. res[5] = G_(Implies_(c, X_(And_(Implies_(neg_b, And_(neg_c, Xn_b)), - Implies_(b, And_(c, Xn_negb)))))); + Implies_(b, And_(c, Xn_negb)))))); } return formula::And(std::move(res)); } @@ -804,12 +804,12 @@ run_jobs() int inc = (j.range.max < j.range.min) ? -1 : 1; int n = j.range.min; for (;;) - { - output_pattern(j.pattern, n); - if (n == j.range.max) - break; - n += inc; - } + { + output_pattern(j.pattern, n); + if (n == j.range.max) + break; + n += inc; + } } } @@ -820,14 +820,14 @@ main(int argc, char** argv) setup(argv); const argp ap = { options, parse_opt, nullptr, argp_program_doc, - children, nullptr, nullptr }; + children, nullptr, nullptr }; if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) exit(err); if (jobs.empty()) error(1, 0, "Nothing to do. Try '%s --help' for more information.", - program_name); + program_name); run_jobs(); return 0; diff --git a/bin/ltl2tgba.cc b/bin/ltl2tgba.cc index 1707a3b67..4a323c5d4 100644 --- a/bin/ltl2tgba.cc +++ b/bin/ltl2tgba.cc @@ -90,9 +90,9 @@ parse_opt(int key, char* arg, struct argp_state*) break; case 'x': { - const char* opt = extra_options.parse_options(arg); - if (opt) - error(2, 0, "failed to parse --options near '%s'", opt); + const char* opt = extra_options.parse_options(arg); + if (opt) + error(2, 0, "failed to parse --options near '%s'", opt); } break; case ARGP_KEY_ARG: @@ -122,19 +122,19 @@ namespace int process_formula(spot::formula f, - const char* filename = nullptr, int linenum = 0) + const char* filename = nullptr, int linenum = 0) { // This should not happen, because the parser we use can only // read PSL/LTL formula, but since our formula type can // represent more than PSL formula, let's make this // future-proof. if (!f.is_psl_formula()) - { - std::string s = spot::str_psl(f); - error_at_line(2, 0, filename, linenum, - "formula '%s' is not an LTL or PSL formula", - s.c_str()); - } + { + std::string s = spot::str_psl(f); + error_at_line(2, 0, filename, linenum, + "formula '%s' is not an LTL or PSL formula", + s.c_str()); + } spot::stopwatch sw; sw.start(); @@ -142,7 +142,7 @@ namespace const double translation_time = sw.stop(); printer.print(aut, f, filename, linenum, translation_time, nullptr, - prefix, suffix); + prefix, suffix); return 0; } }; @@ -157,7 +157,7 @@ main(int argc, char** argv) setup(argv); const argp ap = { options, parse_opt, "[FORMULA...]", - argp_program_doc, children, nullptr, nullptr }; + argp_program_doc, children, nullptr, nullptr }; simplification_level = 3; @@ -166,7 +166,7 @@ main(int argc, char** argv) if (jobs.empty()) error(2, 0, "No formula to translate? Run '%s --help' for usage.", - program_name); + program_name); spot::translator trans(&extra_options); trans.set_pref(pref | comp | sbacc | unambig); @@ -177,7 +177,7 @@ main(int argc, char** argv) { trans_processor processor(trans); if (processor.run()) - return 2; + return 2; } catch (const std::runtime_error& e) { diff --git a/bin/ltl2tgta.cc b/bin/ltl2tgta.cc index 8078397d8..5bbe47e70 100644 --- a/bin/ltl2tgta.cc +++ b/bin/ltl2tgta.cc @@ -119,9 +119,9 @@ parse_opt(int key, char* arg, struct argp_state*) break; case 'x': { - const char* opt = extra_options.parse_options(arg); - if (opt) - error(2, 0, "failed to parse --options near '%s'", opt); + const char* opt = extra_options.parse_options(arg); + if (opt) + error(2, 0, "failed to parse --options near '%s'", opt); } break; case OPT_TGTA: @@ -171,7 +171,7 @@ namespace int process_formula(spot::formula f, - const char* filename = nullptr, int linenum = 0) + const char* filename = nullptr, int linenum = 0) { auto aut = trans.run(&f); @@ -180,33 +180,33 @@ namespace // represent more than PSL formula, let's make this // future-proof. if (!f.is_psl_formula()) - { - std::string s = spot::str_psl(f); - error_at_line(2, 0, filename, linenum, - "formula '%s' is not an LTL or PSL formula", - s.c_str()); - } + { + std::string s = spot::str_psl(f); + error_at_line(2, 0, filename, linenum, + "formula '%s' is not an LTL or PSL formula", + s.c_str()); + } bdd ap_set = atomic_prop_collect_as_bdd(f, aut); if (ta_type != TGTA) - { - auto testing_automaton = - tgba_to_ta(aut, ap_set, type == spot::postprocessor::BA, - opt_with_artificial_initial_state, - opt_single_pass_emptiness_check, - opt_with_artificial_livelock); - if (level != spot::postprocessor::Low) - testing_automaton = spot::minimize_ta(testing_automaton); - spot::print_dot(std::cout, testing_automaton); - } + { + auto testing_automaton = + tgba_to_ta(aut, ap_set, type == spot::postprocessor::BA, + opt_with_artificial_initial_state, + opt_single_pass_emptiness_check, + opt_with_artificial_livelock); + if (level != spot::postprocessor::Low) + testing_automaton = spot::minimize_ta(testing_automaton); + spot::print_dot(std::cout, testing_automaton); + } else - { - auto tgta = tgba_to_tgta(aut, ap_set); - if (level != spot::postprocessor::Low) - tgta = spot::minimize_tgta(tgta); - spot::print_dot(std::cout, tgta->get_ta()); - } + { + auto tgta = tgba_to_tgta(aut, ap_set); + if (level != spot::postprocessor::Low) + tgta = spot::minimize_tgta(tgta); + spot::print_dot(std::cout, tgta->get_ta()); + } flush_cout(); return 0; } @@ -219,7 +219,7 @@ main(int argc, char** argv) setup(argv); const argp ap = { options, parse_opt, "[FORMULA...]", - argp_program_doc, children, nullptr, nullptr }; + argp_program_doc, children, nullptr, nullptr }; simplification_level = 3; @@ -228,7 +228,7 @@ main(int argc, char** argv) if (jobs.empty()) error(2, 0, "No formula to translate? Run '%s --help' for usage.", - program_name); + program_name); spot::translator trans(&extra_options); trans.set_pref(pref | comp | sbacc); diff --git a/bin/ltlcross.cc b/bin/ltlcross.cc index 1c84e536c..b2f8942a2 100644 --- a/bin/ltlcross.cc +++ b/bin/ltlcross.cc @@ -299,22 +299,22 @@ struct statistics if (show_exit) os << "\"exit_status\",\"exit_code\","; os << ("\"time\"," - "\"states\"," - "\"edges\"," - "\"transitions\"," - "\"acc\"," - "\"scc\"," - "\"nonacc_scc\"," - "\"terminal_scc\"," - "\"weak_scc\"," - "\"strong_scc\"," - "\"nondet_states\"," - "\"nondet_aut\"," - "\"terminal_aut\"," - "\"weak_aut\"," - "\"strong_aut\"," - "\"ambiguous_aut\"," - "\"complete_aut\""); + "\"states\"," + "\"edges\"," + "\"transitions\"," + "\"acc\"," + "\"scc\"," + "\"nonacc_scc\"," + "\"terminal_scc\"," + "\"weak_scc\"," + "\"strong_scc\"," + "\"nondet_states\"," + "\"nondet_aut\"," + "\"terminal_aut\"," + "\"weak_aut\"," + "\"strong_aut\"," + "\"ambiguous_aut\"," + "\"complete_aut\""); size_t m = products_avg ? 1U : products; for (size_t i = 0; i < m; ++i) os << ",\"product_states\",\"product_transitions\",\"product_scc\""; @@ -324,70 +324,70 @@ struct statistics void to_csv(std::ostream& os, bool show_exit, const char* na = "", - bool csv_escape = true) + bool csv_escape = true) { if (show_exit) os << '"' << status_str << "\"," << status_code << ','; os << time << ','; if (ok) { - os << states << ',' - << edges << ',' - << transitions << ',' - << acc << ',' - << scc << ',' - << nonacc_scc << ',' - << terminal_scc << ',' - << weak_scc << ',' - << strong_scc << ',' - << nondetstates << ',' - << nondeterministic << ',' - << terminal_aut << ',' - << weak_aut << ',' - << strong_aut << ',' - << ambiguous << ',' - << complete; - if (!products_avg) - { - for (size_t i = 0; i < products; ++i) - os << ',' << product_states[i] - << ',' << product_transitions[i] - << ',' << product_scc[i]; - } - else - { - double st = 0.0; - double tr = 0.0; - double sc = 0.0; - for (size_t i = 0; i < products; ++i) - { - st += product_states[i]; - tr += product_transitions[i]; - sc += product_scc[i]; - } - os << ',' << (st / products) - << ',' << (tr / products) - << ',' << (sc / products); - } + os << states << ',' + << edges << ',' + << transitions << ',' + << acc << ',' + << scc << ',' + << nonacc_scc << ',' + << terminal_scc << ',' + << weak_scc << ',' + << strong_scc << ',' + << nondetstates << ',' + << nondeterministic << ',' + << terminal_aut << ',' + << weak_aut << ',' + << strong_aut << ',' + << ambiguous << ',' + << complete; + if (!products_avg) + { + for (size_t i = 0; i < products; ++i) + os << ',' << product_states[i] + << ',' << product_transitions[i] + << ',' << product_scc[i]; + } + else + { + double st = 0.0; + double tr = 0.0; + double sc = 0.0; + for (size_t i = 0; i < products; ++i) + { + st += product_states[i]; + tr += product_transitions[i]; + sc += product_scc[i]; + } + os << ',' << (st / products) + << ',' << (tr / products) + << ',' << (sc / products); + } } else { - size_t m = products_avg ? 1U : products; - m *= 3; - m += 15; - os << na; - for (size_t i = 0; i < m; ++i) - os << ',' << na; + size_t m = products_avg ? 1U : products; + m *= 3; + m += 15; + os << na; + for (size_t i = 0; i < m; ++i) + os << ',' << na; } if (opt_automata) { - os << ','; - if (hoa_str.empty()) - os << na; - else if (csv_escape) - spot::escape_rfc4180(os << '"', hoa_str) << '"'; - else - spot::escape_str(os << '"', hoa_str) << '"'; + os << ','; + if (hoa_str.empty()) + os << na; + else if (csv_escape) + spot::escape_rfc4180(os << '"', hoa_str) << '"'; + else + spot::escape_str(os << '"', hoa_str) << '"'; } } }; @@ -415,17 +415,17 @@ parse_opt(int key, char* arg, struct argp_state*) break; case OPT_BOGUS: { - bogus_output = new output_file(arg); - bogus_output_filename = arg; - break; + bogus_output = new output_file(arg); + bogus_output_filename = arg; + break; } case OPT_COLOR: { - if (arg) - color_opt = XARGMATCH("--color", arg, color_args, color_types); - else - color_opt = color_always; - break; + if (arg) + color_opt = XARGMATCH("--color", arg, color_args, color_types); + else + color_opt = color_always; + break; } case OPT_CSV: want_stats = true; @@ -449,10 +449,10 @@ parse_opt(int key, char* arg, struct argp_state*) break; case OPT_PRODUCTS: if (*arg == '+') - { - products_avg = false; - ++arg; - } + { + products_avg = false; + ++arg; + } products = to_pos_int(arg); break; case OPT_NOCHECKS: @@ -495,7 +495,7 @@ namespace spot::twa_graph_ptr translate(unsigned int translator_num, char l, statistics_formula* fstats, - bool& problem) + bool& problem) { output.reset(translator_num); @@ -504,7 +504,7 @@ namespace std::string cmd = command.str(); std::cerr << "Running [" << l << translator_num << "]: " - << cmd << std::endl; + << cmd << std::endl; spot::stopwatch sw; sw.start(); int es = exec_with_timeout(cmd.c_str()); @@ -514,128 +514,128 @@ namespace spot::twa_graph_ptr res = nullptr; if (timed_out) - { - // This is not considered to be a global error. - std::cerr << "warning: timeout during execution of command\n"; - ++timeout_count; - status_str = "timeout"; - problem = false; // A timeout is not a sign of a bug - es = -1; - } + { + // This is not considered to be a global error. + std::cerr << "warning: timeout during execution of command\n"; + ++timeout_count; + status_str = "timeout"; + problem = false; // A timeout is not a sign of a bug + es = -1; + } else if (WIFSIGNALED(es)) - { - status_str = "signal"; - problem = true; - es = WTERMSIG(es); - global_error() << "error: execution terminated by signal " - << es << ".\n"; - end_error(); - } + { + status_str = "signal"; + problem = true; + es = WTERMSIG(es); + global_error() << "error: execution terminated by signal " + << es << ".\n"; + end_error(); + } else if (WIFEXITED(es) && WEXITSTATUS(es) != 0) - { - es = WEXITSTATUS(es); - status_str = "exit code"; - if (!ignore_exec_fail) - { - problem = true; - global_error() << "error: execution returned exit code " - << es << ".\n"; - end_error(); - } - else - { - problem = false; - std::cerr << "warning: execution returned exit code " - << es << ".\n"; - ++ignored_exec_fail; - } - } + { + es = WEXITSTATUS(es); + status_str = "exit code"; + if (!ignore_exec_fail) + { + problem = true; + global_error() << "error: execution returned exit code " + << es << ".\n"; + end_error(); + } + else + { + problem = false; + std::cerr << "warning: execution returned exit code " + << es << ".\n"; + ++ignored_exec_fail; + } + } else - { - status_str = "ok"; - problem = false; - es = 0; + { + status_str = "ok"; + problem = false; + es = 0; - auto aut = spot::parse_aut(output.val()->name(), dict, - spot::default_environment::instance(), - opt_parse); - if (!aut->errors.empty()) - { - status_str = "parse error"; - problem = true; - es = -1; - std::ostream& err = global_error(); - err << "error: failed to parse the produced automaton.\n"; - aut->format_errors(err); - end_error(); - res = nullptr; - } - else if (aut->aborted) - { - status_str = "aborted"; - problem = true; - es = -1; - global_error() << "error: aborted HOA file.\n"; - end_error(); - res = nullptr; - } - else - { - res = aut->aut; - } - } + auto aut = spot::parse_aut(output.val()->name(), dict, + spot::default_environment::instance(), + opt_parse); + if (!aut->errors.empty()) + { + status_str = "parse error"; + problem = true; + es = -1; + std::ostream& err = global_error(); + err << "error: failed to parse the produced automaton.\n"; + aut->format_errors(err); + end_error(); + res = nullptr; + } + else if (aut->aborted) + { + status_str = "aborted"; + problem = true; + es = -1; + global_error() << "error: aborted HOA file.\n"; + end_error(); + res = nullptr; + } + else + { + res = aut->aut; + } + } if (want_stats) - { - statistics* st = &(*fstats)[translator_num]; - st->status_str = status_str; - st->status_code = es; - st->time = duration; + { + statistics* st = &(*fstats)[translator_num]; + st->status_str = status_str; + st->status_code = es; + st->time = duration; - // Compute statistics. - if (res) - { - if (verbose) - std::cerr << "info: getting statistics\n"; - st->ok = true; - spot::twa_sub_statistics s = sub_stats_reachable(res); - st->states = s.states; - st->edges = s.edges; - st->transitions = s.transitions; - st->acc = res->acc().num_sets(); - spot::scc_info m(res); - unsigned c = m.scc_count(); - st->scc = c; - st->nondetstates = spot::count_nondet_states(res); - st->nondeterministic = st->nondetstates != 0; - for (unsigned n = 0; n < c; ++n) - { - if (m.is_rejecting_scc(n)) - ++st->nonacc_scc; - else if (is_terminal_scc(m, n)) - ++st->terminal_scc; - else if (is_weak_scc(m, n)) - ++st->weak_scc; - else - ++st->strong_scc; - } - if (st->strong_scc) - st->strong_aut = true; - else if (st->weak_scc) - st->weak_aut = true; - else - st->terminal_aut = true; - st->ambiguous = !spot::is_unambiguous(res); - st->complete = spot::is_complete(res); + // Compute statistics. + if (res) + { + if (verbose) + std::cerr << "info: getting statistics\n"; + st->ok = true; + spot::twa_sub_statistics s = sub_stats_reachable(res); + st->states = s.states; + st->edges = s.edges; + st->transitions = s.transitions; + st->acc = res->acc().num_sets(); + spot::scc_info m(res); + unsigned c = m.scc_count(); + st->scc = c; + st->nondetstates = spot::count_nondet_states(res); + st->nondeterministic = st->nondetstates != 0; + for (unsigned n = 0; n < c; ++n) + { + if (m.is_rejecting_scc(n)) + ++st->nonacc_scc; + else if (is_terminal_scc(m, n)) + ++st->terminal_scc; + else if (is_weak_scc(m, n)) + ++st->weak_scc; + else + ++st->strong_scc; + } + if (st->strong_scc) + st->strong_aut = true; + else if (st->weak_scc) + st->weak_aut = true; + else + st->terminal_aut = true; + st->ambiguous = !spot::is_unambiguous(res); + st->complete = spot::is_complete(res); - if (opt_automata) - { - std::ostringstream os; - spot::print_hoa(os, res, "l"); - st->hoa_str = os.str(); - } - } - } + if (opt_automata) + { + std::ostringstream os; + spot::print_hoa(os, res, "l"); + st->hoa_str = os.str(); + } + } + } output.cleanup(); return res; } @@ -643,74 +643,74 @@ namespace static bool check_empty_prod(const spot::const_twa_graph_ptr& aut_i, - const spot::const_twa_graph_ptr& aut_j, - size_t i, size_t j, bool icomp, bool jcomp) + const spot::const_twa_graph_ptr& aut_j, + size_t i, size_t j, bool icomp, bool jcomp) { if (aut_i->num_sets() + aut_j->num_sets() - > 8 * sizeof(spot::acc_cond::mark_t::value_t)) + > 8 * sizeof(spot::acc_cond::mark_t::value_t)) { - // Report the skipped test if both automata are not - // complemented, or the --verbose option is used, - if (!verbose && (icomp || jcomp)) - return false; - std::cerr << "info: building "; - if (icomp) - std::cerr << "Comp(N" << i << ')'; - else - std::cerr << 'P' << i; - if (jcomp) - std::cerr << "*Comp(P" << j << ')'; - else - std::cerr << "*N" << j; - std::cerr << " requires more acceptance sets than supported\n"; - return false; + // Report the skipped test if both automata are not + // complemented, or the --verbose option is used, + if (!verbose && (icomp || jcomp)) + return false; + std::cerr << "info: building "; + if (icomp) + std::cerr << "Comp(N" << i << ')'; + else + std::cerr << 'P' << i; + if (jcomp) + std::cerr << "*Comp(P" << j << ')'; + else + std::cerr << "*N" << j; + std::cerr << " requires more acceptance sets than supported\n"; + return false; } auto prod = spot::product(aut_i, aut_j); if (verbose) { - std::cerr << "info: check_empty "; - if (icomp) - std::cerr << "Comp(N" << i << ')'; - else - std::cerr << 'P' << i; - if (jcomp) - std::cerr << "*Comp(P" << j << ')'; - else - std::cerr << "*N" << j; - std::cerr << '\n'; + std::cerr << "info: check_empty "; + if (icomp) + std::cerr << "Comp(N" << i << ')'; + else + std::cerr << 'P' << i; + if (jcomp) + std::cerr << "*Comp(P" << j << ')'; + else + std::cerr << "*N" << j; + std::cerr << '\n'; } auto res = spot::couvreur99(prod)->check(); if (res) { - std::ostream& err = global_error(); - err << "error: "; - if (icomp) - err << "Comp(N" << i << ')'; - else - err << 'P' << i; - if (jcomp) - err << "*Comp(P" << j << ')'; - else - err << "*N" << j; - err << " is nonempty"; + std::ostream& err = global_error(); + err << "error: "; + if (icomp) + err << "Comp(N" << i << ')'; + else + err << 'P' << i; + if (jcomp) + err << "*Comp(P" << j << ')'; + else + err << "*N" << j; + err << " is nonempty"; - auto run = res->accepting_run(); - if (run) - { - std::cerr << "; both automata accept the infinite word\n" - << " "; - spot::twa_word w(run->reduce()); - w.simplify(); - example() << w << '\n'; - } - else - { - std::cerr << '\n'; - } - end_error(); + auto run = res->accepting_run(); + if (run) + { + std::cerr << "; both automata accept the infinite word\n" + << " "; + spot::twa_word w(run->reduce()); + w.simplify(); + example() << w << '\n'; + } + else + { + std::cerr << '\n'; + } + end_error(); } return !!res; } @@ -721,18 +721,18 @@ namespace size_t m = maps.size(); if (verbose) { - std::cerr << "info: cross_check {"; - bool first = true; - for (size_t i = 0; i < m; ++i) - if (maps[i]) - { - if (first) - first = false; - else - std::cerr << ','; - std::cerr << l << i; - } - std::cerr << "}, state-space #" << p << '/' << products << '\n'; + std::cerr << "info: cross_check {"; + bool first = true; + for (size_t i = 0; i < m; ++i) + if (maps[i]) + { + if (first) + first = false; + else + std::cerr << ','; + std::cerr << l << i; + } + std::cerr << "}, state-space #" << p << '/' << products << '\n'; } std::vector res(m); @@ -740,53 +740,53 @@ namespace unsigned violated = 0; for (size_t i = 0; i < m; ++i) if (spot::scc_info* m = maps[i]) - { - // r == true iff the automaton i is accepting. - bool r = false; - for (auto& scc: *m) - if (scc.is_accepting()) - { - r = true; - break; - } - res[i] = r; - if (r) - ++verified; - else - ++violated; - } + { + // r == true iff the automaton i is accepting. + bool r = false; + for (auto& scc: *m) + if (scc.is_accepting()) + { + r = true; + break; + } + res[i] = r; + if (r) + ++verified; + else + ++violated; + } if (verified != 0 && violated != 0) { - std::ostream& err = global_error(); - err << "error: {"; - bool first = true; - for (size_t i = 0; i < m; ++i) - if (maps[i] && res[i]) - { - if (first) - first = false; - else - err << ','; - err << l << i; - } - err << "} disagree with {"; - first = true; - for (size_t i = 0; i < m; ++i) - if (maps[i] && !res[i]) - { - if (first) - first = false; - else - err << ','; - err << l << i; - } - err << "} when evaluating "; - if (products > 1) - err << "state-space #" << p << '/' << products << '\n'; - else - err << "the state-space\n"; - end_error(); - return true; + std::ostream& err = global_error(); + err << "error: {"; + bool first = true; + for (size_t i = 0; i < m; ++i) + if (maps[i] && res[i]) + { + if (first) + first = false; + else + err << ','; + err << l << i; + } + err << "} disagree with {"; + first = true; + for (size_t i = 0; i < m; ++i) + if (maps[i] && !res[i]) + { + if (first) + first = false; + else + err << ','; + err << l << i; + } + err << "} when evaluating "; + if (products > 1) + err << "state-space #" << p << '/' << products << '\n'; + else + err << "the state-space\n"; + end_error(); + return true; } return false; } @@ -802,9 +802,9 @@ namespace auto ps = aut->get_named_prop("product-states"); for (auto& scc: *m) if (scc.is_accepting() || scc.is_trivial()) - for (auto i: scc.states()) - // Get the projection on sspace. - s.insert((*ps)[i].second); + for (auto i: scc.states()) + // Get the projection on sspace. + s.insert((*ps)[i].second); } static bool @@ -834,118 +834,118 @@ namespace int process_string(const std::string& input, - const char* filename, - int linenum) + const char* filename, + int linenum) { auto pf = parse_formula(input); if (!pf.f || !pf.errors.empty()) - { - if (filename) - error_at_line(0, 0, filename, linenum, "parse error:"); - pf.format_errors(std::cerr); - return 1; - } + { + if (filename) + error_at_line(0, 0, filename, linenum, "parse error:"); + pf.format_errors(std::cerr); + return 1; + } auto f = pf.f; int res = process_formula(f, filename, linenum); if (res && bogus_output) - bogus_output->ostream() << input << std::endl; + bogus_output->ostream() << input << std::endl; if (res && grind_output) - { - std::string bogus = input; - std::vector mutations; - unsigned mutation_count; - unsigned mutation_max; - while (res) - { - std::cerr << "Trying to find a bogus mutation of "; - if (color_opt) - std::cerr << bright_blue; - std::cerr << bogus; - if (color_opt) - std::cerr << reset_color; - std::cerr << "...\n"; + { + std::string bogus = input; + std::vector mutations; + unsigned mutation_count; + unsigned mutation_max; + while (res) + { + std::cerr << "Trying to find a bogus mutation of "; + if (color_opt) + std::cerr << bright_blue; + std::cerr << bogus; + if (color_opt) + std::cerr << reset_color; + std::cerr << "...\n"; - mutations = mutate(f); - mutation_count = 1; - mutation_max = mutations.size(); - res = 0; - for (auto g: mutations) - { - std::cerr << "Mutation " << mutation_count << '/' - << mutation_max << ": "; - f = g; - res = process_formula(g); - if (res) - break; - ++mutation_count; - } - if (res) - { - if (lbt_input) - bogus = spot::str_lbt_ltl(f); - else - bogus = spot::str_psl(f); - if (bogus_output) - bogus_output->ostream() << bogus << std::endl; - } - } - std::cerr << "Smallest bogus mutation found for "; - if (color_opt) - std::cerr << bright_blue; - std::cerr << input; - if (color_opt) - std::cerr << reset_color; - std::cerr << " is "; - if (color_opt) - std::cerr << bright_blue; - std::cerr << bogus; - if (color_opt) - std::cerr << reset_color; - std::cerr << ".\n\n"; - grind_output->ostream() << bogus << std::endl; - } + mutations = mutate(f); + mutation_count = 1; + mutation_max = mutations.size(); + res = 0; + for (auto g: mutations) + { + std::cerr << "Mutation " << mutation_count << '/' + << mutation_max << ": "; + f = g; + res = process_formula(g); + if (res) + break; + ++mutation_count; + } + if (res) + { + if (lbt_input) + bogus = spot::str_lbt_ltl(f); + else + bogus = spot::str_psl(f); + if (bogus_output) + bogus_output->ostream() << bogus << std::endl; + } + } + std::cerr << "Smallest bogus mutation found for "; + if (color_opt) + std::cerr << bright_blue; + std::cerr << input; + if (color_opt) + std::cerr << reset_color; + std::cerr << " is "; + if (color_opt) + std::cerr << bright_blue; + std::cerr << bogus; + if (color_opt) + std::cerr << reset_color; + std::cerr << ".\n\n"; + grind_output->ostream() << bogus << std::endl; + } return 0; } void product_stats(statistics_formula* stats, unsigned i, - spot::scc_info* sm) + spot::scc_info* sm) { if (verbose && sm) - std::cerr << "info: " << sm->scc_count() - << " SCCs\n"; + std::cerr << "info: " << sm->scc_count() + << " SCCs\n"; // Statistics if (want_stats) - { - if (sm) - { - (*stats)[i].product_scc.push_back(sm->scc_count()); - spot::twa_statistics s = spot::stats_reachable(sm->get_aut()); - (*stats)[i].product_states.push_back(s.states); - (*stats)[i].product_transitions.push_back(s.edges); - } - else - { - double n = nan(""); - (*stats)[i].product_scc.push_back(n); - (*stats)[i].product_states.push_back(n); - (*stats)[i].product_transitions.push_back(n); - } - } + { + if (sm) + { + (*stats)[i].product_scc.push_back(sm->scc_count()); + spot::twa_statistics s = spot::stats_reachable(sm->get_aut()); + (*stats)[i].product_states.push_back(s.states); + (*stats)[i].product_transitions.push_back(s.edges); + } + else + { + double n = nan(""); + (*stats)[i].product_scc.push_back(n); + (*stats)[i].product_states.push_back(n); + (*stats)[i].product_transitions.push_back(n); + } + } } int process_formula(spot::formula f, - const char* filename = nullptr, int linenum = 0) + const char* filename = nullptr, int linenum = 0) { static unsigned round = 0; // If we need LBT atomic proposition in any of the input or // output, relabel the formula. if (!f.has_lbt_atomic_props() && - (runner.has('l') || runner.has('L') || runner.has('T'))) - f = spot::relabel(f, spot::Pnn); + (runner.has('l') || runner.has('L') || runner.has('T'))) + f = spot::relabel(f, spot::Pnn); // ---------- Positive Formula ---------- @@ -955,30 +955,30 @@ namespace // complains. std::string fstr = runner.formula(); if (filename) - std::cerr << filename << ':'; + std::cerr << filename << ':'; if (linenum) - std::cerr << linenum << ':'; + std::cerr << linenum << ':'; if (filename || linenum) - std::cerr << ' '; + std::cerr << ' '; if (color_opt) - std::cerr << bright_blue; + std::cerr << bright_blue; std::cerr << fstr << '\n'; if (color_opt) - std::cerr << reset_color; + std::cerr << reset_color; // Make sure we do not translate the same formula twice. if (!allow_dups) - { - if (!unique_set.insert(f).second) - { - std::cerr - << ("warning: This formula or its negation has already" - " been checked.\n Use --allow-dups if it " - "should not be ignored.\n") - << std::endl; - return 0; - } - } + { + if (!unique_set.insert(f).second) + { + std::cerr + << ("warning: This formula or its negation has already" + " been checked.\n Use --allow-dups if it " + "should not be ignored.\n") + << std::endl; + return 0; + } + } int problems = 0; @@ -1002,337 +1002,337 @@ namespace formulas.push_back(fstr); for (size_t n = 0; n < m; ++n) - { - bool prob; - pos[n] = runner.translate(n, 'P', pstats, prob); - problems += prob; + { + bool prob; + pos[n] = runner.translate(n, 'P', pstats, prob); + problems += prob; - // If the automaton is deterministic, compute its complement - // as well. Note that if we have computed statistics - // already, there is no need to call is_deterministic() - // again. - if (!no_complement && pos[n] - && ((want_stats && !(*pstats)[n].nondeterministic) - || (!want_stats && is_deterministic(pos[n])))) - comp_pos[n] = dtwa_complement(pos[n]); - } + // If the automaton is deterministic, compute its complement + // as well. Note that if we have computed statistics + // already, there is no need to call is_deterministic() + // again. + if (!no_complement && pos[n] + && ((want_stats && !(*pstats)[n].nondeterministic) + || (!want_stats && is_deterministic(pos[n])))) + comp_pos[n] = dtwa_complement(pos[n]); + } // ---------- Negative Formula ---------- // The negative formula is only needed when checks are // activated. if (!no_checks) - { - nstats = &vstats[n + 1]; - nstats->resize(m); + { + nstats = &vstats[n + 1]; + nstats->resize(m); - spot::formula nf = spot::formula::Not(f); + spot::formula nf = spot::formula::Not(f); - if (!allow_dups) - { - bool res = unique_set.insert(nf).second; - // It is not possible to discover that nf has already been - // translated, otherwise that would mean that f had been - // translated too and we would have caught it before. - assert(res); - (void) res; - } + if (!allow_dups) + { + bool res = unique_set.insert(nf).second; + // It is not possible to discover that nf has already been + // translated, otherwise that would mean that f had been + // translated too and we would have caught it before. + assert(res); + (void) res; + } - runner.round_formula(nf, round); - formulas.push_back(runner.formula()); + runner.round_formula(nf, round); + formulas.push_back(runner.formula()); - for (size_t n = 0; n < m; ++n) - { - bool prob; - neg[n] = runner.translate(n, 'N', nstats, prob); - problems += prob; + for (size_t n = 0; n < m; ++n) + { + bool prob; + neg[n] = runner.translate(n, 'N', nstats, prob); + problems += prob; - // If the automaton is deterministic, compute its - // complement as well. Note that if we have computed - // statistics already, there is no need to call - // is_deterministic() again. - if (!no_complement && neg[n] - && ((want_stats && !(*nstats)[n].nondeterministic) - || (!want_stats && is_deterministic(neg[n])))) - comp_neg[n] = dtwa_complement(neg[n]); - } - } + // If the automaton is deterministic, compute its + // complement as well. Note that if we have computed + // statistics already, there is no need to call + // is_deterministic() again. + if (!no_complement && neg[n] + && ((want_stats && !(*nstats)[n].nondeterministic) + || (!want_stats && is_deterministic(neg[n])))) + comp_neg[n] = dtwa_complement(neg[n]); + } + } spot::cleanup_tmpfiles(); ++round; if (!no_checks) - { - std::cerr << "Performing sanity checks and gathering statistics..." - << std::endl; + { + std::cerr << "Performing sanity checks and gathering statistics..." + << std::endl; - auto printsize = [](const spot::const_twa_graph_ptr& aut) - { - std::cerr << aut->num_states() << " st.," + auto printsize = [](const spot::const_twa_graph_ptr& aut) + { + std::cerr << aut->num_states() << " st.," << aut->num_edges() << " ed.," << aut->num_sets() << " sets"; - }; + }; - if (determinize && !no_complement) - { - bool print_first = verbose; - auto tmp = [&](std::vector& from, - std::vector& to, unsigned i, - char prefix) - { - if (!to[i]) - { - if (print_first) - { - std::cerr << "info: complementing non-deterministic " - "automata via determinization...\n"; - print_first = false; - } - spot::postprocessor p; - p.set_type(spot::postprocessor::Generic); - p.set_pref(spot::postprocessor::Deterministic); - p.set_level(spot::postprocessor::Low); - to[i] = dtwa_complement(p.run(from[i])); - if (verbose) - { - std::cerr << "info: " << prefix << i << "\t("; - printsize(from[i]); - std::cerr << ") -> ("; - printsize(to[i]); - std::cerr << ")\tComp(" << prefix << i << ")\n"; - } - } - }; - for (unsigned i = 0; i < m; ++i) - { - tmp(pos, comp_pos, i, 'P'); - tmp(neg, comp_neg, i, 'N'); - } - } + if (determinize && !no_complement) + { + bool print_first = verbose; + auto tmp = [&](std::vector& from, + std::vector& to, unsigned i, + char prefix) + { + if (!to[i]) + { + if (print_first) + { + std::cerr << "info: complementing non-deterministic " + "automata via determinization...\n"; + print_first = false; + } + spot::postprocessor p; + p.set_type(spot::postprocessor::Generic); + p.set_pref(spot::postprocessor::Deterministic); + p.set_level(spot::postprocessor::Low); + to[i] = dtwa_complement(p.run(from[i])); + if (verbose) + { + std::cerr << "info: " << prefix << i << "\t("; + printsize(from[i]); + std::cerr << ") -> ("; + printsize(to[i]); + std::cerr << ")\tComp(" << prefix << i << ")\n"; + } + } + }; + for (unsigned i = 0; i < m; ++i) + { + tmp(pos, comp_pos, i, 'P'); + tmp(neg, comp_neg, i, 'N'); + } + } - bool print_first = verbose; - auto tmp = [&](std::vector& x, unsigned i, - const char* prefix, const char* suffix) - { - if (!x[i]) - return; - cleanup_acceptance_here(x[i]); - if (x[i]->acc().uses_fin_acceptance()) - { - if (verbose) - { - if (print_first) - { - std::cerr << - "info: getting rid of any Fin acceptance...\n"; - print_first = false; - } - std::cerr << "info:\t" << prefix << i - << suffix << "\t("; - printsize(x[i]); - std::cerr << ") ->"; - } - x[i] = remove_fin(x[i]); - if (verbose) - { - std::cerr << " ("; - printsize(x[i]); - std::cerr << ")\n"; - } - } - }; - for (unsigned i = 0; i < m; ++i) - { - tmp(pos, i, " P", " "); - tmp(neg, i, " N", " "); - tmp(comp_pos, i, "Comp(P", ")"); - tmp(comp_neg, i, "Comp(N", ")"); - } + bool print_first = verbose; + auto tmp = [&](std::vector& x, unsigned i, + const char* prefix, const char* suffix) + { + if (!x[i]) + return; + cleanup_acceptance_here(x[i]); + if (x[i]->acc().uses_fin_acceptance()) + { + if (verbose) + { + if (print_first) + { + std::cerr << + "info: getting rid of any Fin acceptance...\n"; + print_first = false; + } + std::cerr << "info:\t" << prefix << i + << suffix << "\t("; + printsize(x[i]); + std::cerr << ") ->"; + } + x[i] = remove_fin(x[i]); + if (verbose) + { + std::cerr << " ("; + printsize(x[i]); + std::cerr << ")\n"; + } + } + }; + for (unsigned i = 0; i < m; ++i) + { + tmp(pos, i, " P", " "); + tmp(neg, i, " N", " "); + tmp(comp_pos, i, "Comp(P", ")"); + tmp(comp_neg, i, "Comp(N", ")"); + } - // intersection test - for (size_t i = 0; i < m; ++i) - if (pos[i]) - for (size_t j = 0; j < m; ++j) - if (neg[j]) - { - problems += - check_empty_prod(pos[i], neg[j], i, j, false, false); + // intersection test + for (size_t i = 0; i < m; ++i) + if (pos[i]) + for (size_t j = 0; j < m; ++j) + if (neg[j]) + { + problems += + check_empty_prod(pos[i], neg[j], i, j, false, false); - // Deal with the extra complemented automata if we - // have some. + // Deal with the extra complemented automata if we + // have some. - // If comp_pos[j] and comp_neg[j] exist for the - // same j, it means pos[j] and neg[j] were both - // deterministic. In that case, we will want to - // make sure that comp_pos[j]*comp_neg[j] is empty - // to assert the complementary of pos[j] and - // neg[j]. However using comp_pos[j] and - // comp_neg[j] against other translator will not - // give us any more insight than pos[j] and - // neg[j]. So we only do intersection checks with - // a complement automata when one of the two - // translation was not deterministic. + // If comp_pos[j] and comp_neg[j] exist for the + // same j, it means pos[j] and neg[j] were both + // deterministic. In that case, we will want to + // make sure that comp_pos[j]*comp_neg[j] is empty + // to assert the complementary of pos[j] and + // neg[j]. However using comp_pos[j] and + // comp_neg[j] against other translator will not + // give us any more insight than pos[j] and + // neg[j]. So we only do intersection checks with + // a complement automata when one of the two + // translation was not deterministic. - if (i != j && comp_pos[j] && !comp_neg[j]) - problems += - check_empty_prod(pos[i], comp_pos[j], - i, j, false, true); - if (i != j && comp_neg[i] && !comp_pos[i]) - problems += - check_empty_prod(comp_neg[i], neg[j], - i, j, true, false); - if (comp_pos[i] && comp_neg[j] && - (i == j || (!comp_neg[i] && !comp_pos[j]))) - problems += - check_empty_prod(comp_pos[i], comp_neg[j], - i, j, true, true); - } - } + if (i != j && comp_pos[j] && !comp_neg[j]) + problems += + check_empty_prod(pos[i], comp_pos[j], + i, j, false, true); + if (i != j && comp_neg[i] && !comp_pos[i]) + problems += + check_empty_prod(comp_neg[i], neg[j], + i, j, true, false); + if (comp_pos[i] && comp_neg[j] && + (i == j || (!comp_neg[i] && !comp_pos[j]))) + problems += + check_empty_prod(comp_pos[i], comp_neg[j], + i, j, true, true); + } + } else - { - std::cerr << "Gathering statistics..." << std::endl; - } + { + std::cerr << "Gathering statistics..." << std::endl; + } spot::atomic_prop_set* ap = spot::atomic_prop_collect(f); if (want_stats) - for (size_t i = 0; i < m; ++i) - { - (*pstats)[i].product_states.reserve(products); - (*pstats)[i].product_transitions.reserve(products); - (*pstats)[i].product_scc.reserve(products); - if (neg[i]) - { - (*nstats)[i].product_states.reserve(products); - (*nstats)[i].product_transitions.reserve(products); - (*nstats)[i].product_scc.reserve(products); - } - } + for (size_t i = 0; i < m; ++i) + { + (*pstats)[i].product_states.reserve(products); + (*pstats)[i].product_transitions.reserve(products); + (*pstats)[i].product_scc.reserve(products); + if (neg[i]) + { + (*nstats)[i].product_states.reserve(products); + (*nstats)[i].product_transitions.reserve(products); + (*nstats)[i].product_scc.reserve(products); + } + } for (unsigned p = 0; p < products; ++p) - { - // build a random state-space. - spot::srand(seed); + { + // build a random state-space. + spot::srand(seed); - if (verbose) - std::cerr << "info: building state-space #" << p << '/' << products - << " of " << states << " states with seed " << seed - << '\n'; + if (verbose) + std::cerr << "info: building state-space #" << p << '/' << products + << " of " << states << " states with seed " << seed + << '\n'; - auto statespace = spot::random_graph(states, density, ap, dict); + auto statespace = spot::random_graph(states, density, ap, dict); - if (verbose) - std::cerr << "info: state-space has " - << statespace->num_edges() - << " edges\n"; + if (verbose) + std::cerr << "info: state-space has " + << statespace->num_edges() + << " edges\n"; - // Associated SCC maps. - std::vector pos_map(m); - std::vector neg_map(m); - for (size_t i = 0; i < m; ++i) - if (pos[i]) - { - if (verbose) - std::cerr << ("info: building product between state-space and" - " P") << i - << " (" << pos[i]->num_states() << " st., " - << pos[i]->num_edges() << " ed.)\n"; + // Associated SCC maps. + std::vector pos_map(m); + std::vector neg_map(m); + for (size_t i = 0; i < m; ++i) + if (pos[i]) + { + if (verbose) + std::cerr << ("info: building product between state-space and" + " P") << i + << " (" << pos[i]->num_states() << " st., " + << pos[i]->num_edges() << " ed.)\n"; - spot::scc_info* sm = nullptr; - try - { - auto p = spot::product(pos[i], statespace); - if (verbose) - std::cerr << "info: product has " << p->num_states() - << " st., " << p->num_edges() - << " ed.\n"; - sm = new spot::scc_info(p); - } - catch (std::bad_alloc&) - { - std::cerr << ("warning: not enough memory to build " - "product of P") << i << " with state-space"; - if (products > 1) - std::cerr << " #" << p << '/' << products << '\n'; - std::cerr << '\n'; - ++oom_count; - } - pos_map[i] = sm; - product_stats(pstats, i, sm); - } + spot::scc_info* sm = nullptr; + try + { + auto p = spot::product(pos[i], statespace); + if (verbose) + std::cerr << "info: product has " << p->num_states() + << " st., " << p->num_edges() + << " ed.\n"; + sm = new spot::scc_info(p); + } + catch (std::bad_alloc&) + { + std::cerr << ("warning: not enough memory to build " + "product of P") << i << " with state-space"; + if (products > 1) + std::cerr << " #" << p << '/' << products << '\n'; + std::cerr << '\n'; + ++oom_count; + } + pos_map[i] = sm; + product_stats(pstats, i, sm); + } - if (!no_checks) - for (size_t i = 0; i < m; ++i) - if (neg[i]) - { - if (verbose) - std::cerr << ("info: building product between state-space" - " and N") << i - << " (" << neg[i]->num_states() << " st., " - << neg[i]->num_edges() << " ed.)\n"; + if (!no_checks) + for (size_t i = 0; i < m; ++i) + if (neg[i]) + { + if (verbose) + std::cerr << ("info: building product between state-space" + " and N") << i + << " (" << neg[i]->num_states() << " st., " + << neg[i]->num_edges() << " ed.)\n"; - spot::scc_info* sm = nullptr; - try - { - auto p = spot::product(neg[i], statespace); - if (verbose) - std::cerr << "info: product has " << p->num_states() - << " st., " << p->num_edges() - << " ed.\n"; - sm = new spot::scc_info(p); - } - catch (std::bad_alloc&) - { - std::cerr << ("warning: not enough memory to build " - "product of N") << i << " with state-space"; - if (products > 1) - std::cerr << " #" << p << '/' << products << '\n'; - std::cerr << '\n'; - ++oom_count; - } + spot::scc_info* sm = nullptr; + try + { + auto p = spot::product(neg[i], statespace); + if (verbose) + std::cerr << "info: product has " << p->num_states() + << " st., " << p->num_edges() + << " ed.\n"; + sm = new spot::scc_info(p); + } + catch (std::bad_alloc&) + { + std::cerr << ("warning: not enough memory to build " + "product of N") << i << " with state-space"; + if (products > 1) + std::cerr << " #" << p << '/' << products << '\n'; + std::cerr << '\n'; + ++oom_count; + } - neg_map[i] = sm; - product_stats(nstats, i, sm); - } + neg_map[i] = sm; + product_stats(nstats, i, sm); + } - if (!no_checks) - { - // cross-comparison test - problems += cross_check(pos_map, 'P', p); - problems += cross_check(neg_map, 'N', p); + if (!no_checks) + { + // cross-comparison test + problems += cross_check(pos_map, 'P', p); + problems += cross_check(neg_map, 'N', p); - // consistency check - for (size_t i = 0; i < m; ++i) - if (pos_map[i] && neg_map[i]) - { - if (verbose) - std::cerr << "info: consistency_check (P" << i - << ",N" << i << "), state-space #" - << p << '/' << products << '\n'; - if (!(consistency_check(pos_map[i], neg_map[i]))) - { - ++problems; + // consistency check + for (size_t i = 0; i < m; ++i) + if (pos_map[i] && neg_map[i]) + { + if (verbose) + std::cerr << "info: consistency_check (P" << i + << ",N" << i << "), state-space #" + << p << '/' << products << '\n'; + if (!(consistency_check(pos_map[i], neg_map[i]))) + { + ++problems; - std::ostream& err = global_error(); - err << "error: inconsistency between P" << i - << " and N" << i; - if (products > 1) - err << " for state-space #" << p - << '/' << products << '\n'; - else - err << '\n'; - end_error(); - } - } - } + std::ostream& err = global_error(); + err << "error: inconsistency between P" << i + << " and N" << i; + if (products > 1) + err << " for state-space #" << p + << '/' << products << '\n'; + else + err << '\n'; + end_error(); + } + } + } - // Cleanup. - if (!no_checks) - for (size_t i = 0; i < m; ++i) - delete neg_map[i]; - for (size_t i = 0; i < m; ++i) - delete pos_map[i]; - ++seed; - } + // Cleanup. + if (!no_checks) + for (size_t i = 0; i < m; ++i) + delete neg_map[i]; + for (size_t i = 0; i < m; ++i) + delete pos_map[i]; + ++seed; + } std::cerr << std::endl; delete ap; @@ -1368,15 +1368,15 @@ print_stats_csv(const char* filename) for (unsigned r = 0; r < rounds; ++r) for (unsigned t = 0; t < ntrans; ++t) if (!opt_omit || vstats[r][t].ok) - { - out << '"'; - spot::escape_rfc4180(out, formulas[r]); - out << "\",\""; - spot::escape_rfc4180(out, translators[t].name); - out << "\","; - vstats[r][t].to_csv(out, !opt_omit); - out << '\n'; - } + { + out << '"'; + spot::escape_rfc4180(out, formulas[r]); + out << "\",\""; + spot::escape_rfc4180(out, translators[t].name); + out << "\","; + vstats[r][t].to_csv(out, !opt_omit); + out << '\n'; + } } static void @@ -1414,14 +1414,14 @@ print_stats_json(const char* filename) for (unsigned r = 0; r < rounds; ++r) for (unsigned t = 0; t < ntrans; ++t) if (!opt_omit || vstats[r][t].ok) - { - if (notfirst) - out << ','; - notfirst = true; - out << "\n [ " << r << ',' << t << ','; - vstats[r][t].to_csv(out, !opt_omit, "null", false); - out << " ]"; - } + { + if (notfirst) + out << ','; + notfirst = true; + out << "\n [ " << r << ',' << t << ','; + vstats[r][t].to_csv(out, !opt_omit, "null", false); + out << " ]"; + } out << "\n ]\n}\n"; } @@ -1431,7 +1431,7 @@ main(int argc, char** argv) setup(argv); const argp ap = { options, parse_opt, "[COMMANDFMT...]", - argp_program_doc, children, nullptr, nullptr }; + argp_program_doc, children, nullptr, nullptr }; if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) exit(err); @@ -1441,7 +1441,7 @@ main(int argc, char** argv) if (translators.empty()) error(2, 0, "No translator to run? Run '%s --help' for usage.", - program_name); + program_name); if (color_opt == color_if_tty) color_opt = isatty(STDERR_FILENO) ? color_always : color_never; @@ -1459,71 +1459,71 @@ main(int argc, char** argv) else { if (global_error_flag) - { - std::ostream& err = global_error(); - if (bogus_output) - err << ("error: some error was detected during the above runs.\n" - " Check file ") - << bogus_output_filename - << " for problematic formulas."; - else - err << ("error: some error was detected during the above runs,\n" - " please search for 'error:' messages in the above" - " trace."); - err << std::endl; - end_error(); - } + { + std::ostream& err = global_error(); + if (bogus_output) + err << ("error: some error was detected during the above runs.\n" + " Check file ") + << bogus_output_filename + << " for problematic formulas."; + else + err << ("error: some error was detected during the above runs,\n" + " please search for 'error:' messages in the above" + " trace."); + err << std::endl; + end_error(); + } else if (timeout_count == 0 && ignored_exec_fail == 0 && oom_count == 0) - { - std::cerr << "No problem detected." << std::endl; - } + { + std::cerr << "No problem detected." << std::endl; + } else - { - std::cerr << "No major problem detected." << std::endl; - } + { + std::cerr << "No major problem detected." << std::endl; + } unsigned additional_errors = 0U; additional_errors += timeout_count > 0; additional_errors += ignored_exec_fail > 0; additional_errors += oom_count > 0; if (additional_errors) - { - std::cerr << (global_error_flag ? "Additionally, " : "However, "); - if (timeout_count) - { - if (additional_errors > 1) - std::cerr << "\n - "; - if (timeout_count == 1) - std::cerr << "1 timeout occurred"; - else - std::cerr << timeout_count << " timeouts occurred"; - } + { + std::cerr << (global_error_flag ? "Additionally, " : "However, "); + if (timeout_count) + { + if (additional_errors > 1) + std::cerr << "\n - "; + if (timeout_count == 1) + std::cerr << "1 timeout occurred"; + else + std::cerr << timeout_count << " timeouts occurred"; + } - if (oom_count) - { - if (additional_errors > 1) - std::cerr << "\n - "; - if (oom_count == 1) - std::cerr << "1 state-space product was"; - else - std::cerr << oom_count << "state-space products were"; - std::cerr << " skipped by lack of memory"; - } + if (oom_count) + { + if (additional_errors > 1) + std::cerr << "\n - "; + if (oom_count == 1) + std::cerr << "1 state-space product was"; + else + std::cerr << oom_count << "state-space products were"; + std::cerr << " skipped by lack of memory"; + } - if (ignored_exec_fail) - { - if (additional_errors > 1) - std::cerr << "\n - "; - if (ignored_exec_fail == 1) - std::cerr << "1 non-zero exit status was ignored"; - else - std::cerr << ignored_exec_fail - << " non-zero exit statuses were ignored"; - } - if (additional_errors == 1) - std::cerr << '.'; - std::cerr << std::endl; - } + if (ignored_exec_fail) + { + if (additional_errors > 1) + std::cerr << "\n - "; + if (ignored_exec_fail == 1) + std::cerr << "1 non-zero exit status was ignored"; + else + std::cerr << ignored_exec_fail + << " non-zero exit statuses were ignored"; + } + if (additional_errors == 1) + std::cerr << '.'; + std::cerr << std::endl; + } } delete bogus_output; diff --git a/bin/ltldo.cc b/bin/ltldo.cc index 3e9450170..1434423d0 100644 --- a/bin/ltldo.cc +++ b/bin/ltldo.cc @@ -151,57 +151,57 @@ namespace spot::twa_graph_ptr res = nullptr; if (timed_out) - { - problem = false; // A timeout is considered benign - std::cerr << "warning: timeout during execution of command \"" - << cmd << "\"\n"; - ++timeout_count; - } + { + problem = false; // A timeout is considered benign + std::cerr << "warning: timeout during execution of command \"" + << cmd << "\"\n"; + ++timeout_count; + } else if (WIFSIGNALED(es)) - { - problem = true; - es = WTERMSIG(es); - std::cerr << "error: execution of command \"" << cmd - << "\" terminated by signal " << es << ".\n"; - } + { + problem = true; + es = WTERMSIG(es); + std::cerr << "error: execution of command \"" << cmd + << "\" terminated by signal " << es << ".\n"; + } else if (WIFEXITED(es) && WEXITSTATUS(es) != 0) - { - problem = true; - es = WEXITSTATUS(es); - std::cerr << "error: execution of command \"" << cmd - << "\" returned exit code " << es << ".\n"; - } + { + problem = true; + es = WEXITSTATUS(es); + std::cerr << "error: execution of command \"" << cmd + << "\" returned exit code " << es << ".\n"; + } else if (output.val()) - { - problem = false; - auto aut = spot::parse_aut(output.val()->name(), dict, - spot::default_environment::instance(), - opt_parse); - if (!aut->errors.empty()) - { - problem = true; - std::cerr << "error: failed to parse the automaton " - "produced by \"" << cmd << "\".\n"; - aut->format_errors(std::cerr); - res = nullptr; - } - else if (aut->aborted) - { - problem = true; - std::cerr << "error: command \"" << cmd - << "\" aborted its output.\n"; - res = nullptr; - } - else - { - res = aut->aut; - } - } - else // No automaton output - { - problem = false; - res = nullptr; - } + { + problem = false; + auto aut = spot::parse_aut(output.val()->name(), dict, + spot::default_environment::instance(), + opt_parse); + if (!aut->errors.empty()) + { + problem = true; + std::cerr << "error: failed to parse the automaton " + "produced by \"" << cmd << "\".\n"; + aut->format_errors(std::cerr); + res = nullptr; + } + else if (aut->aborted) + { + problem = true; + std::cerr << "error: command \"" << cmd + << "\" aborted its output.\n"; + res = nullptr; + } + else + { + res = aut->aut; + } + } + else // No automaton output + { + problem = false; + res = nullptr; + } output.cleanup(); return res; @@ -234,18 +234,18 @@ namespace int process_string(const std::string& input, - const char* filename, - int linenum) + const char* filename, + int linenum) { spot::parsed_formula pf = parse_formula(input); if (!pf.f || !pf.errors.empty()) - { - if (filename) - error_at_line(0, 0, filename, linenum, "parse error:"); - pf.format_errors(std::cerr); - return 1; - } + { + if (filename) + error_at_line(0, 0, filename, linenum, "parse error:"); + pf.format_errors(std::cerr); + return 1; + } inputf = input; process_formula(pf.f, filename, linenum); @@ -255,43 +255,43 @@ namespace int process_formula(spot::formula f, - const char* filename = nullptr, int linenum = 0) + const char* filename = nullptr, int linenum = 0) { std::unique_ptr relmap; // If atomic propositions are incompatible with one of the // output, relabel the formula. if ((!f.has_lbt_atomic_props() && - (runner.has('l') || runner.has('L') || runner.has('T'))) - || (!f.has_spin_atomic_props() && - (runner.has('s') || runner.has('S')))) - { - relmap.reset(new spot::relabeling_map); - f = spot::relabel(f, spot::Pnn, relmap.get()); - } + (runner.has('l') || runner.has('L') || runner.has('T'))) + || (!f.has_spin_atomic_props() && + (runner.has('s') || runner.has('S')))) + { + relmap.reset(new spot::relabeling_map); + f = spot::relabel(f, spot::Pnn, relmap.get()); + } static unsigned round = 1; runner.round_formula(f, round); unsigned ts = translators.size(); for (unsigned t = 0; t < ts; ++t) - { - bool problem; - double translation_time; - auto aut = runner.translate(t, problem, translation_time); - if (problem) - error_at_line(2, 0, filename, linenum, "aborting here"); - if (aut) - { - if (relmap) - relabel_here(aut, relmap.get()); - aut = post.run(aut, f); - cmdname = translators[t].name; - roundval = round; - printer.print(aut, f, filename, linenum, translation_time, - nullptr, prefix, suffix); - }; - } + { + bool problem; + double translation_time; + auto aut = runner.translate(t, problem, translation_time); + if (problem) + error_at_line(2, 0, filename, linenum, "aborting here"); + if (aut) + { + if (relmap) + relabel_here(aut, relmap.get()); + aut = post.run(aut, f); + cmdname = translators[t].name; + roundval = round; + printer.print(aut, f, filename, linenum, translation_time, + nullptr, prefix, suffix); + }; + } spot::cleanup_tmpfiles(); ++round; return 0; @@ -305,7 +305,7 @@ main(int argc, char** argv) setup(argv); const argp ap = { options, parse_opt, "[COMMANDFMT...]", - argp_program_doc, children, nullptr, nullptr }; + argp_program_doc, children, nullptr, nullptr }; // Disable post-processing as much as possible by default. level = spot::postprocessor::Low; @@ -319,7 +319,7 @@ main(int argc, char** argv) if (translators.empty()) error(2, 0, "No translator to run? Run '%s --help' for usage.", - program_name); + program_name); setup_sig_handler(); @@ -332,7 +332,7 @@ main(int argc, char** argv) { processor p(post); if (p.run()) - return 2; + return 2; } catch (const std::runtime_error& e) { diff --git a/bin/ltlfilt.cc b/bin/ltlfilt.cc index 218ffdfa2..caedbdfec 100644 --- a/bin/ltlfilt.cc +++ b/bin/ltlfilt.cc @@ -348,10 +348,10 @@ parse_opt(int key, char* arg, struct argp_state*) break; case OPT_EQUIVALENT_TO: { - if (opt->equivalent_to) - error(2, 0, "only one --equivalent-to option can be given"); - opt->equivalent_to = parse_formula_arg(arg); - break; + if (opt->equivalent_to) + error(2, 0, "only one --equivalent-to option can be given"); + opt->equivalent_to = parse_formula_arg(arg); + break; } case OPT_EXCLUSIVE_AP: opt->excl_ap.add_group(arg); @@ -364,17 +364,17 @@ parse_opt(int key, char* arg, struct argp_state*) break; case OPT_IMPLIED_BY: { - spot::formula i = parse_formula_arg(arg); - // a→c∧b→c ≡ (a∨b)→c - opt->implied_by = spot::formula::Or({opt->implied_by, i}); - break; + spot::formula i = parse_formula_arg(arg); + // a→c∧b→c ≡ (a∨b)→c + opt->implied_by = spot::formula::Or({opt->implied_by, i}); + break; } case OPT_IMPLY: { - // a→b∧a→c ≡ a→(b∧c) - spot::formula i = parse_formula_arg(arg); - opt->imply = spot::formula::And({opt->imply, i}); - break; + // a→b∧a→c ≡ a→(b∧c) + spot::formula i = parse_formula_arg(arg); + opt->imply = spot::formula::And({opt->imply, i}); + break; } case OPT_LTL: ltl = true; @@ -392,13 +392,13 @@ parse_opt(int key, char* arg, struct argp_state*) case OPT_RELABEL_BOOL: relabeling = (key == OPT_RELABEL_BOOL ? BseRelabeling : ApRelabeling); if (!arg || !strncasecmp(arg, "abc", 6)) - style = spot::Abc; + style = spot::Abc; else if (!strncasecmp(arg, "pnn", 4)) - style = spot::Pnn; + style = spot::Pnn; else - error(2, 0, "invalid argument for --relabel%s: '%s'", - (key == OPT_RELABEL_BOOL ? "-bool" : ""), - arg); + error(2, 0, "invalid argument for --relabel%s: '%s'", + (key == OPT_RELABEL_BOOL ? "-bool" : ""), + arg); break; case OPT_REMOVE_WM: unabbreviate += "MW"; @@ -426,9 +426,9 @@ parse_opt(int key, char* arg, struct argp_state*) break; case OPT_UNABBREVIATE: if (arg) - unabbreviate += arg; + unabbreviate += arg; else - unabbreviate += spot::default_unabbrev_string; + unabbreviate += spot::default_unabbrev_string; break; case OPT_AP_N: ap_n = parse_range(arg, 0, std::numeric_limits::max()); @@ -479,87 +479,87 @@ namespace int process_string(const std::string& input, - const char* filename = nullptr, int linenum = 0) + const char* filename = nullptr, int linenum = 0) { spot::parsed_formula pf = parse_formula(input); if (!pf.f || !pf.errors.empty()) - { - if (!ignore_errors) - { - if (filename) - error_at_line(0, 0, filename, linenum, "parse error:"); - pf.format_errors(std::cerr); - } + { + if (!ignore_errors) + { + if (filename) + error_at_line(0, 0, filename, linenum, "parse error:"); + pf.format_errors(std::cerr); + } - if (error_style == skip_errors) - std::cout << input << '\n'; - else - assert(error_style == drop_errors); - check_cout(); - return !ignore_errors; - } + if (error_style == skip_errors) + std::cout << input << '\n'; + else + assert(error_style == drop_errors); + check_cout(); + return !ignore_errors; + } try - { - return process_formula(pf.f, filename, linenum); - } + { + return process_formula(pf.f, filename, linenum); + } catch (const std::runtime_error& e) - { - error_at_line(2, 0, filename, linenum, "%s", e.what()); - SPOT_UNREACHABLE(); - } + { + error_at_line(2, 0, filename, linenum, "%s", e.what()); + SPOT_UNREACHABLE(); + } } int process_formula(spot::formula f, - const char* filename = nullptr, int linenum = 0) + const char* filename = nullptr, int linenum = 0) { if (opt_max_count >= 0 && match_count >= opt_max_count) - { - abort_run = true; - return 0; - } + { + abort_run = true; + return 0; + } if (negate) - f = spot::formula::Not(f); + f = spot::formula::Not(f); if (remove_x) - { - // If simplification are enabled, we do them before and after. - if (simplification_level) - f = simpl.simplify(f); - f = spot::remove_x(f); - } + { + // If simplification are enabled, we do them before and after. + if (simplification_level) + f = simpl.simplify(f); + f = spot::remove_x(f); + } if (simplification_level || boolean_to_isop) - f = simpl.simplify(f); + f = simpl.simplify(f); if (nnf) - f = simpl.negative_normal_form(f); + f = simpl.negative_normal_form(f); switch (relabeling) - { - case ApRelabeling: - { - relmap.clear(); - f = spot::relabel(f, style, &relmap); - break; - } - case BseRelabeling: - { - relmap.clear(); - f = spot::relabel_bse(f, style, &relmap); - break; - } - case NoRelabeling: - break; - } + { + case ApRelabeling: + { + relmap.clear(); + f = spot::relabel(f, style, &relmap); + break; + } + case BseRelabeling: + { + relmap.clear(); + f = spot::relabel_bse(f, style, &relmap); + break; + } + case NoRelabeling: + break; + } if (!unabbreviate.empty()) - f = spot::unabbreviate(f, unabbreviate.c_str()); + f = spot::unabbreviate(f, unabbreviate.c_str()); if (!opt->excl_ap.empty()) - f = opt->excl_ap.constrain(f); + f = opt->excl_ap.constrain(f); bool matched = true; @@ -575,32 +575,32 @@ namespace matched &= !syntactic_persistence || f.is_syntactic_persistence(); matched &= !syntactic_si || f.is_syntactic_stutter_invariant(); if (matched && (ap_n.min > 0 || ap_n.max >= 0)) - { - auto s = atomic_prop_collect(f); - int n = s->size(); - delete s; - matched &= (ap_n.min <= 0) || (n >= ap_n.min); - matched &= (ap_n.max < 0) || (n <= ap_n.max); - } + { + auto s = atomic_prop_collect(f); + int n = s->size(); + delete s; + matched &= (ap_n.min <= 0) || (n >= ap_n.min); + matched &= (ap_n.max < 0) || (n <= ap_n.max); + } if (matched && (size.min > 0 || size.max >= 0)) - { - int l = spot::length(f); - matched &= (size.min <= 0) || (l >= size.min); - matched &= (size.max < 0) || (l <= size.max); - } + { + int l = spot::length(f); + matched &= (size.min <= 0) || (l >= size.min); + matched &= (size.max < 0) || (l <= size.max); + } if (matched && (bsize.min > 0 || bsize.max >= 0)) - { - int l = spot::length_boolone(f); - matched &= (bsize.min <= 0) || (l >= bsize.min); - matched &= (bsize.max < 0) || (l <= bsize.max); - } + { + int l = spot::length_boolone(f); + matched &= (bsize.min <= 0) || (l >= bsize.min); + matched &= (bsize.max < 0) || (l <= bsize.max); + } matched &= !opt->implied_by || simpl.implication(opt->implied_by, f); matched &= !opt->imply || simpl.implication(f, opt->imply); matched &= !opt->equivalent_to - || simpl.are_equivalent(f, opt->equivalent_to); + || simpl.are_equivalent(f, opt->equivalent_to); matched &= !stutter_insensitive || spot::is_stutter_invariant(f); // Match obligations and subclasses using WDBA minimization. @@ -608,46 +608,46 @@ namespace // have to compute it on formulas that have been discarded for // other reasons. if (matched && obligation) - { - auto aut = ltl_to_tgba_fm(f, simpl.get_dict()); - auto min = minimize_obligation(aut, f); - assert(min); - if (aut == min) - { - // Not an obligation - matched = false; - } - else - { - matched &= !guarantee || is_terminal_automaton(min); - matched &= !safety || is_safety_mwdba(min); - } - } + { + auto aut = ltl_to_tgba_fm(f, simpl.get_dict()); + auto min = minimize_obligation(aut, f); + assert(min); + if (aut == min) + { + // Not an obligation + matched = false; + } + else + { + matched &= !guarantee || is_terminal_automaton(min); + matched &= !safety || is_safety_mwdba(min); + } + } matched ^= invert; if (unique && !unique_set.insert(f).second) - matched = false; + matched = false; if (matched) - { - if (opt->output_define - && output_format != count_output - && output_format != quiet_output) - { - // Sort the formulas alphabetically. - std::map m; - for (auto& p: relmap) - m.emplace(str_psl(p.first), p.second); - for (auto& p: m) - stream_formula(opt->output_define->ostream() - << "#define " << p.first << " (", - p.second, filename, linenum) << ")\n"; - } - one_match = true; - output_formula_checked(f, filename, linenum, prefix, suffix); - ++match_count; - } + { + if (opt->output_define + && output_format != count_output + && output_format != quiet_output) + { + // Sort the formulas alphabetically. + std::map m; + for (auto& p: relmap) + m.emplace(str_psl(p.first), p.second); + for (auto& p: m) + stream_formula(opt->output_define->ostream() + << "#define " << p.first << " (", + p.second, filename, linenum) << ")\n"; + } + one_match = true; + output_formula_checked(f, filename, linenum, prefix, suffix); + ++match_count; + } return 0; } }; @@ -659,7 +659,7 @@ main(int argc, char** argv) setup(argv); const argp ap = { options, parse_opt, "[FILENAME[/COL]...]", - argp_program_doc, children, nullptr, nullptr }; + argp_program_doc, children, nullptr, nullptr }; try { @@ -669,20 +669,20 @@ main(int argc, char** argv) opt = &o; if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) - exit(err); + exit(err); if (jobs.empty()) - jobs.emplace_back("-", 1); + jobs.emplace_back("-", 1); if (boolean_to_isop && simplification_level == 0) - simplification_level = 1; + simplification_level = 1; spot::tl_simplifier_options opt(simplification_level); opt.boolean_to_isop = boolean_to_isop; spot::tl_simplifier simpl(opt); ltl_processor processor(simpl); if (processor.run()) - return 2; + return 2; } catch (const std::runtime_error& e) { diff --git a/bin/ltlgrind.cc b/bin/ltlgrind.cc index cd6f26654..0085804be 100644 --- a/bin/ltlgrind.cc +++ b/bin/ltlgrind.cc @@ -113,12 +113,12 @@ namespace public: int process_formula(spot::formula f, const char* filename = nullptr, - int linenum = 0) + int linenum = 0) { auto mutations = - spot::mutate(f, mut_opts, max_output, mutation_nb, opt_sort); + spot::mutate(f, mut_opts, max_output, mutation_nb, opt_sort); for (auto g: mutations) - output_formula_checked(g, filename, linenum, prefix, suffix); + output_formula_checked(g, filename, linenum, prefix, suffix); return 0; } }; @@ -182,7 +182,7 @@ main(int argc, char* argv[]) setup(argv); const argp ap = { options, parse_opt, "[FILENAME[/COL]...]", argp_program_doc, - children, nullptr, nullptr }; + children, nullptr, nullptr }; if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) exit(err); diff --git a/bin/randaut.cc b/bin/randaut.cc index 58dd51047..ac65ac2e7 100644 --- a/bin/randaut.cc +++ b/bin/randaut.cc @@ -191,24 +191,24 @@ parse_opt(int key, char* arg, struct argp_state* as) case 'a': opt_acc_prob = to_float(arg); if (opt_acc_prob < 0.0 || opt_acc_prob > 1.0) - error(2, 0, "probability of acceptance set membership " - "should be between 0.0 and 1.0"); + error(2, 0, "probability of acceptance set membership " + "should be between 0.0 and 1.0"); break; case 'A': if (looks_like_a_range(arg)) - { - opt_acc_sets = parse_range(arg); - if (opt_acc_sets.min > opt_acc_sets.max) - std::swap(opt_acc_sets.min, opt_acc_sets.max); - if (opt_acc_sets.min < 0) - error(2, 0, "number of acceptance sets should be positive"); - gba_wanted = true; - } + { + opt_acc_sets = parse_range(arg); + if (opt_acc_sets.min > opt_acc_sets.max) + std::swap(opt_acc_sets.min, opt_acc_sets.max); + if (opt_acc_sets.min < 0) + error(2, 0, "number of acceptance sets should be positive"); + gba_wanted = true; + } else - { - opt_acceptance = arg; - generic_wanted = true; - } + { + opt_acceptance = arg; + generic_wanted = true; + } break; case 'B': ba_options(); @@ -217,7 +217,7 @@ parse_opt(int key, char* arg, struct argp_state* as) case 'e': opt_density = to_float(arg); if (opt_density < 0.0 || opt_density > 1.0) - error(2, 0, "density should be between 0.0 and 1.0"); + error(2, 0, "density should be between 0.0 and 1.0"); break; case 'D': opt_deterministic = true; @@ -228,9 +228,9 @@ parse_opt(int key, char* arg, struct argp_state* as) case 'Q': opt_states = parse_range(arg); if (opt_states.min > opt_states.max) - std::swap(opt_states.min, opt_states.max); + std::swap(opt_states.min, opt_states.max); if (opt_states.min == 0) - error(1, 0, "cannot build an automaton with 0 states"); + error(1, 0, "cannot build an automaton with 0 states"); break; case 'S': opt_state_acc = true; @@ -255,14 +255,14 @@ parse_opt(int key, char* arg, struct argp_state* as) // last non-option argument, and if aprops.empty() we know this // is the also the first one. if (opt->aprops.empty() - && as->argc == as->next && looks_like_a_range(arg)) - { - ap_count_given = parse_range(arg); - // Create the set once if the count is fixed. - if (ap_count_given.min == ap_count_given.max) - opt->aprops = spot::create_atomic_prop_set(ap_count_given.min); - break; - } + && as->argc == as->next && looks_like_a_range(arg)) + { + ap_count_given = parse_range(arg); + // Create the set once if the count is fixed. + if (ap_count_given.min == ap_count_given.max) + opt->aprops = spot::create_atomic_prop_set(ap_count_given.min); + break; + } opt->aprops.insert(spot::formula::ap(arg)); break; @@ -281,7 +281,7 @@ main(int argc, char** argv) setup(argv); const argp ap = { options, parse_opt, "N|PROP...", argp_program_doc, - children, nullptr, nullptr }; + children, nullptr, nullptr }; try { @@ -291,43 +291,43 @@ main(int argc, char** argv) opt = &o; if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) - exit(err); + exit(err); // running 'randaut 0' is one way to generate automata using no // atomic propositions so do not complain in that case. if (opt->aprops.empty() && ap_count_given.max < 0) - error(2, 0, - "No atomic proposition supplied? Run '%s --help' for usage.", - program_name); + error(2, 0, + "No atomic proposition supplied? Run '%s --help' for usage.", + program_name); if (generic_wanted && automaton_format == Spin) - error(2, 0, - "--spin implies --ba so should not be used with --acceptance"); + error(2, 0, + "--spin implies --ba so should not be used with --acceptance"); if (generic_wanted && ba_wanted) - error(2, 0, "--acceptance and --ba may not be used together"); + error(2, 0, "--acceptance and --ba may not be used together"); if (automaton_format == Spin && opt_acc_sets.max > 1) - error(2, 0, "--spin is incompatible with --acceptance=%d..%d", - opt_acc_sets.min, opt_acc_sets.max); + error(2, 0, "--spin is incompatible with --acceptance=%d..%d", + opt_acc_sets.min, opt_acc_sets.max); if (ba_wanted && opt_acc_sets.min != 1 && opt_acc_sets.max != 1) - error(2, 0, "--ba is incompatible with --acceptance=%d..%d", - opt_acc_sets.min, opt_acc_sets.max); + error(2, 0, "--ba is incompatible with --acceptance=%d..%d", + opt_acc_sets.min, opt_acc_sets.max); if (ba_wanted && generic_wanted) - error(2, 0, - "--ba is incompatible with --acceptance=%s", opt_acceptance); + error(2, 0, + "--ba is incompatible with --acceptance=%s", opt_acceptance); if (automaton_format == Spin) - ba_options(); + ba_options(); if (opt_colored && opt_acc_sets.min == -1 && !generic_wanted) - error(2, 0, "--colored requires at least one acceptance set; " - "use --acceptance"); + error(2, 0, "--colored requires at least one acceptance set; " + "use --acceptance"); if (opt_colored && opt_acc_sets.min == 0) - error(2, 0, "--colored requires at least one acceptance set; " - "fix the range of --acceptance"); + error(2, 0, "--colored requires at least one acceptance set; " + "fix the range of --acceptance"); if (opt_acc_sets.min == -1) - opt_acc_sets.min = 0; + opt_acc_sets.min = 0; spot::srand(opt_seed); auto d = spot::make_bdd_dict(); @@ -340,70 +340,70 @@ main(int argc, char** argv) int automaton_num = 0; for (;;) - { - spot::stopwatch sw; - sw.start(); + { + spot::stopwatch sw; + sw.start(); - if (ap_count_given.max > 0 - && ap_count_given.min != ap_count_given.max) - { - int c = spot::rrand(ap_count_given.min, ap_count_given.max); - opt->aprops = spot::create_atomic_prop_set(c); - } + if (ap_count_given.max > 0 + && ap_count_given.min != ap_count_given.max) + { + int c = spot::rrand(ap_count_given.min, ap_count_given.max); + opt->aprops = spot::create_atomic_prop_set(c); + } - int size = opt_states.min; - if (size != opt_states.max) - size = spot::rrand(size, opt_states.max); + int size = opt_states.min; + if (size != opt_states.max) + size = spot::rrand(size, opt_states.max); - int accs = opt_acc_sets.min; - if (accs != opt_acc_sets.max) - accs = spot::rrand(accs, opt_acc_sets.max); + int accs = opt_acc_sets.min; + if (accs != opt_acc_sets.max) + accs = spot::rrand(accs, opt_acc_sets.max); - spot::acc_cond::acc_code code; - if (opt_acceptance) - { - code = spot::acc_cond::acc_code(opt_acceptance); - accs = code.used_sets().max_set(); - if (opt_colored && accs == 0) - error(2, 0, "--colored requires at least one acceptance set; " - "fix the range of --acceptance"); - } + spot::acc_cond::acc_code code; + if (opt_acceptance) + { + code = spot::acc_cond::acc_code(opt_acceptance); + accs = code.used_sets().max_set(); + if (opt_colored && accs == 0) + error(2, 0, "--colored requires at least one acceptance set; " + "fix the range of --acceptance"); + } - auto aut = - spot::random_graph(size, opt_density, &opt->aprops, d, - accs, opt_acc_prob, 0.5, - opt_deterministic, opt_state_acc, - opt_colored); + auto aut = + spot::random_graph(size, opt_density, &opt->aprops, d, + accs, opt_acc_prob, 0.5, + opt_deterministic, opt_state_acc, + opt_colored); - if (opt_acceptance) - aut->set_acceptance(accs, code); + if (opt_acceptance) + aut->set_acceptance(accs, code); - if (opt_uniq) - { - auto tmp = spot::canonicalize - (make_twa_graph(aut, spot::twa::prop_set::all())); - std::vector trans(tmp->edge_vector().begin() + 1, - tmp->edge_vector().end()); - if (!opt_uniq->emplace(trans).second) - { - --trials; - if (trials == 0) - error(2, 0, "failed to generate a new unique automaton" - " after %d trials", max_trials); - continue; - } - trials = max_trials; - } + if (opt_uniq) + { + auto tmp = spot::canonicalize + (make_twa_graph(aut, spot::twa::prop_set::all())); + std::vector trans(tmp->edge_vector().begin() + 1, + tmp->edge_vector().end()); + if (!opt_uniq->emplace(trans).second) + { + --trials; + if (trials == 0) + error(2, 0, "failed to generate a new unique automaton" + " after %d trials", max_trials); + continue; + } + trials = max_trials; + } - auto runtime = sw.stop(); + auto runtime = sw.stop(); - printer.print(aut, nullptr, - opt_seed_str, automaton_num, runtime, nullptr); + printer.print(aut, nullptr, + opt_seed_str, automaton_num, runtime, nullptr); - ++automaton_num; - if (opt_automata > 0 && automaton_num >= opt_automata) - break; - } + ++automaton_num; + if (opt_automata > 0 && automaton_num >= opt_automata) + break; + } } catch (const std::runtime_error& e) { diff --git a/bin/randltl.cc b/bin/randltl.cc index 091ff3b3b..45cf6c507 100644 --- a/bin/randltl.cc +++ b/bin/randltl.cc @@ -197,7 +197,7 @@ parse_opt(int key, char* arg, struct argp_state* as) case OPT_TREE_SIZE: opt_tree_size = parse_range(arg); if (opt_tree_size.min > opt_tree_size.max) - std::swap(opt_tree_size.min, opt_tree_size.max); + std::swap(opt_tree_size.min, opt_tree_size.max); break; case OPT_WF: opt_wf = true; @@ -211,16 +211,16 @@ parse_opt(int key, char* arg, struct argp_state* as) // last non-option argument, and if aprops.empty() we know this // is the also the first one. if (opt->aprops.empty() && as->argc == as->next) - { - char* endptr; - int res = strtol(arg, &endptr, 10); - if (!*endptr && res >= 0) // arg is a number - { - ap_count_given = true; - opt->aprops = spot::create_atomic_prop_set(res); - break; - } - } + { + char* endptr; + int res = strtol(arg, &endptr, 10); + if (!*endptr && res >= 0) // arg is a number + { + ap_count_given = true; + opt->aprops = spot::create_atomic_prop_set(res); + break; + } + } opt->aprops.insert(spot::default_environment::instance().require(arg)); break; default: @@ -235,7 +235,7 @@ main(int argc, char** argv) setup(argv); const argp ap = { options, parse_opt, "N|PROP...", argp_program_doc, - children, nullptr, nullptr }; + children, nullptr, nullptr }; try { @@ -245,78 +245,78 @@ main(int argc, char** argv) opt = &o; if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) - exit(err); + exit(err); // running 'randltl 0' is one way to generate formulas using no // atomic propositions so do not complain in that case. if (opt->aprops.empty() && !ap_count_given) - error(2, 0, "No atomic proposition supplied? " - "Run '%s --help' for usage.", program_name); + error(2, 0, "No atomic proposition supplied? " + "Run '%s --help' for usage.", program_name); spot::srand(opt_seed); spot::randltlgenerator rg - (opt->aprops, - [&] (){ - spot::option_map opts; - opts.set("output", output); - opts.set("tree_size_min", opt_tree_size.min); - opts.set("tree_size_max", opt_tree_size.max); - opts.set("wf", opt_wf); - opts.set("seed", opt_seed); - opts.set("simplification_level", simplification_level); - return opts; - }(), opt_pL, opt_pS, opt_pB); + (opt->aprops, + [&] (){ + spot::option_map opts; + opts.set("output", output); + opts.set("tree_size_min", opt_tree_size.min); + opts.set("tree_size_max", opt_tree_size.max); + opts.set("wf", opt_wf); + opts.set("seed", opt_seed); + opts.set("simplification_level", simplification_level); + return opts; + }(), opt_pL, opt_pS, opt_pB); if (opt_dump_priorities) - { - switch (output) - { - case OUTPUTLTL: - std::cout << - "Use --ltl-priorities to set the following LTL priorities:\n"; - rg.dump_ltl_priorities(std::cout); - break; - case OUTPUTBOOL: - std::cout << - "Use --boolean-priorities to set the following Boolean " - "formula priorities:\n"; - rg.dump_bool_priorities(std::cout); - break; - case OUTPUTPSL: - std::cout << - "Use --ltl-priorities to set the following LTL priorities:\n"; - rg.dump_psl_priorities(std::cout); - // Fall through. - case OUTPUTSERE: - std::cout << - "Use --sere-priorities to set the following SERE priorities:\n"; - rg.dump_sere_priorities(std::cout); - std::cout << - "Use --boolean-priorities to set the following Boolean " - "formula priorities:\n"; - rg.dump_sere_bool_priorities(std::cout); - break; - default: - error(2, 0, "internal error: unknown type of output"); - } - exit(0); - } + { + switch (output) + { + case OUTPUTLTL: + std::cout << + "Use --ltl-priorities to set the following LTL priorities:\n"; + rg.dump_ltl_priorities(std::cout); + break; + case OUTPUTBOOL: + std::cout << + "Use --boolean-priorities to set the following Boolean " + "formula priorities:\n"; + rg.dump_bool_priorities(std::cout); + break; + case OUTPUTPSL: + std::cout << + "Use --ltl-priorities to set the following LTL priorities:\n"; + rg.dump_psl_priorities(std::cout); + // Fall through. + case OUTPUTSERE: + std::cout << + "Use --sere-priorities to set the following SERE priorities:\n"; + rg.dump_sere_priorities(std::cout); + std::cout << + "Use --boolean-priorities to set the following Boolean " + "formula priorities:\n"; + rg.dump_sere_bool_priorities(std::cout); + break; + default: + error(2, 0, "internal error: unknown type of output"); + } + exit(0); + } while (opt_formulas < 0 || opt_formulas--) - { - static int count = 0; - spot::formula f = rg.next(); - if (!f) - { - error(2, 0, "failed to generate a new unique formula after %d " \ - "trials", MAX_TRIALS); - } - else - { - output_formula_checked(f, nullptr, ++count); - } - }; + { + static int count = 0; + spot::formula f = rg.next(); + if (!f) + { + error(2, 0, "failed to generate a new unique formula after %d " \ + "trials", MAX_TRIALS); + } + else + { + output_formula_checked(f, nullptr, ++count); + } + }; } catch (const std::runtime_error& e) { diff --git a/bin/spot-x.cc b/bin/spot-x.cc index 7a9fa580d..7d9cd893d 100644 --- a/bin/spot-x.cc +++ b/bin/spot-x.cc @@ -113,7 +113,7 @@ Enabled by default.") }, if the TGBA is not already deterministic. Doing so will degeneralize \ the automaton. This is disabled by default, unless sat-minimize is set.") }, { DOC("sat-minimize", - "Set to 1 to enable SAT-based minimization of deterministic \ + "Set to 1 to enable SAT-based minimization of deterministic \ TGBA: it starts with the number of states of the input, and iteratively \ tries to find a deterministic TGBA with one less state. Set to 2 to perform \ a binary search instead. Disabled (0) by default. The sat solver to use \ @@ -123,7 +123,7 @@ set; this can be changed with the sat-acc option, or of course by using -B \ to construct a Büchi automaton. Enabling SAT-based minimization will \ also enable tba-det.") }, { DOC("sat-states", - "When this is set to some positive integer, the SAT-based \ + "When this is set to some positive integer, the SAT-based \ minimization will attempt to construct a TGBA with the given number of \ states. It may however return an automaton with less states if some of \ these are unreachable or useless. Setting sat-states automatically \ @@ -131,13 +131,13 @@ enables sat-minimize, but no iteration is performed. If no equivalent \ automaton could be constructed with the given number of states, the original \ automaton is returned.") }, { DOC("sat-acc", - "When this is set to some positive integer, the SAT-based will \ + "When this is set to some positive integer, the SAT-based will \ attempt to construct a TGBA with the given number of acceptance sets. \ states. It may however return an automaton with less acceptance sets if \ some of these are useless. Setting sat-acc automatically \ sets sat-minimize to 1 if not set differently.") }, { DOC("state-based", - "Set to 1 to instruct the SAT-minimization procedure to produce \ + "Set to 1 to instruct the SAT-minimization procedure to produce \ a TGBA where all outgoing transition of a state have the same acceptance \ sets. By default this is only enabled when option -B is used.") }, { nullptr, 0, nullptr, 0, nullptr, 0 } @@ -155,13 +155,13 @@ main(int argc, char** argv) setup(argv); const argp ap = { options, nullptr, nullptr, argp_program_doc, children, - nullptr, nullptr }; + nullptr, nullptr }; if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) exit(err); std::cerr << "This binary serves no purpose other than generating" - << " the spot-x.7 manpage.\n"; + << " the spot-x.7 manpage.\n"; return 1; } diff --git a/spot/graph/graph.hh b/spot/graph/graph.hh index 6d9127c04..07401c125 100644 --- a/spot/graph/graph.hh +++ b/spot/graph/graph.hh @@ -47,7 +47,7 @@ namespace spot struct first_is_base_of { static const bool value = - std::is_base_of::type>::value; + std::is_base_of::type>::value; }; #endif @@ -65,11 +65,11 @@ namespace spot #ifndef SWIG template ::value>::type> - boxed_label(Args&&... args) - noexcept(std::is_nothrow_constructible::value) - : label{std::forward(args)...} + typename = typename std::enable_if< + !first_is_base_of::value>::type> + boxed_label(Args&&... args) + noexcept(std::is_nothrow_constructible::value) + : label{std::forward(args)...} { } #endif @@ -77,23 +77,23 @@ namespace spot // if Data is a POD type, G++ 4.8.2 wants default values for all // label fields unless we define this default constructor here. explicit boxed_label() - noexcept(std::is_nothrow_constructible::value) + noexcept(std::is_nothrow_constructible::value) { } Data& data() { - return label; + return label; } const Data& data() const { - return label; + return label; } bool operator<(const boxed_label& other) const { - return label < other.label; + return label < other.label; } }; @@ -103,12 +103,12 @@ namespace spot typedef std::tuple<> data_t; std::tuple<>& data() { - return *this; + return *this; } const std::tuple<>& data() const { - return *this; + return *this; } }; @@ -120,11 +120,11 @@ namespace spot #ifndef SWIG template ::value>::type> - boxed_label(Args&&... args) - noexcept(std::is_nothrow_constructible::value) - : Data{std::forward(args)...} + typename = typename std::enable_if< + !first_is_base_of::value>::type> + boxed_label(Args&&... args) + noexcept(std::is_nothrow_constructible::value) + : Data{std::forward(args)...} { } #endif @@ -132,18 +132,18 @@ namespace spot // if Data is a POD type, G++ 4.8.2 wants default values for all // label fields unless we define this default constructor here. explicit boxed_label() - noexcept(std::is_nothrow_constructible::value) + noexcept(std::is_nothrow_constructible::value) { } Data& data() { - return *this; + return *this; } const Data& data() const { - return *this; + return *this; } }; @@ -158,15 +158,15 @@ namespace spot struct SPOT_API distate_storage final: public State_Data { Edge succ = 0; // First outgoing edge (used when iterating) - Edge succ_tail = 0; // Last outgoing edge (used for - // appending new edges) + Edge succ_tail = 0; // Last outgoing edge (used for + // appending new edges) #ifndef SWIG template ::value>::type> + typename = typename std::enable_if< + !first_is_base_of::value>::type> distate_storage(Args&&... args) - noexcept(std::is_nothrow_constructible::value) - : State_Data{std::forward(args)...} + noexcept(std::is_nothrow_constructible::value) + : State_Data{std::forward(args)...} { } #endif @@ -179,47 +179,47 @@ namespace spot // Again two implementation: one with label, and one without. template + typename StateOut, typename Edge, typename Edge_Data> struct SPOT_API edge_storage final: public Edge_Data { typedef Edge edge; - StateOut dst; // destination - Edge next_succ; // next outgoing edge with same - // source, or 0 - StateIn src; // source + StateOut dst; // destination + Edge next_succ; // next outgoing edge with same + // source, or 0 + StateIn src; // source explicit edge_storage() - noexcept(std::is_nothrow_constructible::value) - : Edge_Data{} + noexcept(std::is_nothrow_constructible::value) + : Edge_Data{} { } #ifndef SWIG template edge_storage(StateOut dst, Edge next_succ, - StateIn src, Args&&... args) - noexcept(std::is_nothrow_constructible::value - && std::is_nothrow_constructible::value - && std::is_nothrow_constructible::value) - : Edge_Data{std::forward(args)...}, - dst(dst), next_succ(next_succ), src(src) + StateIn src, Args&&... args) + noexcept(std::is_nothrow_constructible::value + && std::is_nothrow_constructible::value + && std::is_nothrow_constructible::value) + : Edge_Data{std::forward(args)...}, + dst(dst), next_succ(next_succ), src(src) { } #endif bool operator<(const edge_storage& other) const { - if (src < other.src) - return true; - if (src > other.src) - return false; - // This might be costly if the destination is a vector - if (dst < other.dst) - return true; - if (dst > other.dst) - return false; - return this->data() < other.data(); + if (src < other.src) + return true; + if (src > other.src) + return false; + // This might be costly if the destination is a vector + if (dst < other.dst) + return true; + if (dst > other.dst) + return false; + return this->data() < other.data(); } bool operator==(const edge_storage& other) const @@ -241,86 +241,86 @@ namespace spot template class SPOT_API edge_iterator: public std::iterator::value, - const typename Graph::edge_storage_t, - typename Graph::edge_storage_t>::type> + typename + std::conditional::value, + const typename Graph::edge_storage_t, + typename Graph::edge_storage_t>::type> { typedef - std::iterator::value, - const typename Graph::edge_storage_t, - typename Graph::edge_storage_t>::type> - super; + std::iterator::value, + const typename Graph::edge_storage_t, + typename Graph::edge_storage_t>::type> + super; public: typedef typename Graph::edge edge; edge_iterator() noexcept - : g_(nullptr), t_(0) + : g_(nullptr), t_(0) { } edge_iterator(Graph* g, edge t) noexcept - : g_(g), t_(t) + : g_(g), t_(t) { } bool operator==(edge_iterator o) const { - return t_ == o.t_; + return t_ == o.t_; } bool operator!=(edge_iterator o) const { - return t_ != o.t_; + return t_ != o.t_; } typename super::reference operator*() { - return g_->edge_storage(t_); + return g_->edge_storage(t_); } const typename super::reference operator*() const { - return g_->edge_storage(t_); + return g_->edge_storage(t_); } typename super::pointer operator->() { - return &g_->edge_storage(t_); + return &g_->edge_storage(t_); } const typename super::pointer operator->() const { - return &g_->edge_storage(t_); + return &g_->edge_storage(t_); } edge_iterator operator++() { - t_ = operator*().next_succ; - return *this; + t_ = operator*().next_succ; + return *this; } edge_iterator operator++(int) { - edge_iterator ti = *this; - t_ = operator*().next_succ; - return ti; + edge_iterator ti = *this; + t_ = operator*().next_succ; + return ti; } operator bool() const { - return t_; + return t_; } edge trans() const { - return t_; + return t_; } protected: @@ -337,52 +337,52 @@ namespace spot typedef typename Graph::edge edge; killer_edge_iterator(Graph* g, edge t, state_storage_t& src) noexcept - : super(g, t), src_(src), prev_(0) + : super(g, t), src_(src), prev_(0) { } killer_edge_iterator operator++() { - prev_ = this->t_; - this->t_ = this->operator*().next_succ; - return *this; + prev_ = this->t_; + this->t_ = this->operator*().next_succ; + return *this; } killer_edge_iterator operator++(int) { - killer_edge_iterator ti = *this; - ++*this; - return ti; + killer_edge_iterator ti = *this; + ++*this; + return ti; } // Erase the current edge and advance the iterator. void erase() { - edge next = this->operator*().next_succ; + edge next = this->operator*().next_succ; - // Update source state and previous edges - if (prev_) - { - this->g_->edge_storage(prev_).next_succ = next; - } - else - { - if (src_.succ == this->t_) - src_.succ = next; - } - if (src_.succ_tail == this->t_) - { - src_.succ_tail = prev_; - assert(next == 0); - } + // Update source state and previous edges + if (prev_) + { + this->g_->edge_storage(prev_).next_succ = next; + } + else + { + if (src_.succ == this->t_) + src_.succ = next; + } + if (src_.succ_tail == this->t_) + { + src_.succ_tail = prev_; + assert(next == 0); + } - // Erased edges have themselves as next_succ. - this->operator*().next_succ = this->t_; + // Erased edges have themselves as next_succ. + this->operator*().next_succ = this->t_; - // Advance iterator to next edge. - this->t_ = next; + // Advance iterator to next edge. + this->t_ = next; - ++this->g_->killed_edge_; + ++this->g_->killed_edge_; } protected: @@ -403,23 +403,23 @@ namespace spot public: typedef typename Graph::edge edge; state_out(Graph* g, edge t) noexcept - : g_(g), t_(t) + : g_(g), t_(t) { } edge_iterator begin() { - return {g_, t_}; + return {g_, t_}; } edge_iterator end() { - return {}; + return {}; } void recycle(edge t) { - t_ = t; + t_ = t; } protected: @@ -434,92 +434,92 @@ namespace spot template class SPOT_API all_edge_iterator: public std::iterator::value, - const typename Graph::edge_storage_t, - typename Graph::edge_storage_t>::type> + typename + std::conditional::value, + const typename Graph::edge_storage_t, + typename Graph::edge_storage_t>::type> { typedef - std::iterator::value, - const typename Graph::edge_storage_t, - typename Graph::edge_storage_t>::type> - super; + std::iterator::value, + const typename Graph::edge_storage_t, + typename Graph::edge_storage_t>::type> + super; typedef typename std::conditional::value, - const typename Graph::edge_vector_t, - typename Graph::edge_vector_t>::type - tv_t; + const typename Graph::edge_vector_t, + typename Graph::edge_vector_t>::type + tv_t; unsigned t_; tv_t& tv_; void skip_() { - unsigned s = tv_.size(); - do - ++t_; - while (t_ < s && tv_[t_].next_succ == t_); + unsigned s = tv_.size(); + do + ++t_; + while (t_ < s && tv_[t_].next_succ == t_); } public: all_edge_iterator(unsigned pos, tv_t& tv) noexcept - : t_(pos), tv_(tv) + : t_(pos), tv_(tv) { - skip_(); + skip_(); } all_edge_iterator(tv_t& tv) noexcept - : t_(tv.size()), tv_(tv) + : t_(tv.size()), tv_(tv) { } all_edge_iterator& operator++() { - skip_(); - return *this; + skip_(); + return *this; } all_edge_iterator operator++(int) { - all_edge_iterator old = *this; - ++*this; - return old; + all_edge_iterator old = *this; + ++*this; + return old; } bool operator==(all_edge_iterator o) const { - return t_ == o.t_; + return t_ == o.t_; } bool operator!=(all_edge_iterator o) const { - return t_ != o.t_; + return t_ != o.t_; } typename super::reference operator*() { - return tv_[t_]; + return tv_[t_]; } const typename super::reference operator*() const { - return tv_[t_]; + return tv_[t_]; } const typename super::pointer operator->() { - return &tv_[t_]; + return &tv_[t_]; } typename super::pointer operator->() const { - return &tv_[t_]; + return &tv_[t_]; } }; @@ -529,27 +529,27 @@ namespace spot { public: typedef typename std::conditional::value, - const typename Graph::edge_vector_t, - typename Graph::edge_vector_t>::type - tv_t; + const typename Graph::edge_vector_t, + typename Graph::edge_vector_t>::type + tv_t; typedef all_edge_iterator iter_t; private: tv_t& tv_; public: all_trans(tv_t& tv) noexcept - : tv_(tv) + : tv_(tv) { } iter_t begin() { - return {0, tv_}; + return {0, tv_}; } iter_t end() { - return {tv_}; + return {tv_}; } }; @@ -586,14 +586,14 @@ namespace spot // The type of an output state (when seen from a edge) // depends on the kind of graph we build typedef typename std::conditional, - state>::type out_state; + std::vector, + state>::type out_state; typedef internal::distate_storage> + internal::boxed_label> state_storage_t; typedef internal::edge_storage> + internal::boxed_label> edge_storage_t; typedef std::vector state_vector; typedef std::vector edge_vector_t; @@ -614,7 +614,7 @@ namespace spot { states_.reserve(max_states); if (max_trans == 0) - max_trans = max_states * 2; + max_trans = max_states * 2; edges_.reserve(max_trans + 1); // Edge number 0 is not used, because we use this index // to mark the absence of a edge. @@ -638,7 +638,7 @@ namespace spot // Erased edges have their next_succ pointing to // themselves. return (t < edges_.size() && - edges_[t].next_succ != t); + edges_[t].next_succ != t); } template @@ -655,7 +655,7 @@ namespace spot state s = states_.size(); states_.reserve(s + n); while (n--) - states_.emplace_back(std::forward(args)...); + states_.emplace_back(std::forward(args)...); return s; } @@ -730,9 +730,9 @@ namespace spot edge st = states_[src].succ_tail; assert(st < t || !st); if (!st) - states_[src].succ = t; + states_[src].succ = t; else - edges_[st].next_succ = t; + edges_[st].next_succ = t; states_[src].succ_tail = t; return t; } @@ -836,19 +836,19 @@ namespace spot { unsigned tend = edges_.size(); for (unsigned t = 1; t < tend; ++t) - { - o << 't' << t << ": (s" - << edges_[t].src << ", s" - << edges_[t].dst << ") t" - << edges_[t].next_succ << '\n'; - } + { + o << 't' << t << ": (s" + << edges_[t].src << ", s" + << edges_[t].dst << ") t" + << edges_[t].next_succ << '\n'; + } unsigned send = states_.size(); for (unsigned s = 0; s < send; ++s) - { - o << 's' << s << ": t" - << states_[s].succ << " t" - << states_[s].succ_tail << '\n'; - } + { + o << 's' << s << ": t" + << states_[s].succ << " t" + << states_[s].succ_tail << '\n'; + } } // Remove all dead edges. The edges_ vector is left @@ -858,11 +858,11 @@ namespace spot void remove_dead_edges_() { if (killed_edge_ == 0) - return; + return; auto i = std::remove_if(edges_.begin() + 1, edges_.end(), - [this](const edge_storage_t& t) { - return this->is_dead_edge(t); - }); + [this](const edge_storage_t& t) { + return this->is_dead_edge(t); + }); edges_.erase(i, edges_.end()); killed_edge_ = 0; } @@ -885,38 +885,38 @@ namespace spot state last_src = -1U; edge tend = edges_.size(); for (edge t = 1; t < tend; ++t) - { - state src = edges_[t].src; - if (src != last_src) - { - states_[src].succ = t; - if (last_src != -1U) - { - states_[last_src].succ_tail = t - 1; - edges_[t - 1].next_succ = 0; - } - while (++last_src != src) - { - states_[last_src].succ = 0; - states_[last_src].succ_tail = 0; - } - } - else - { - edges_[t - 1].next_succ = t; - } - } + { + state src = edges_[t].src; + if (src != last_src) + { + states_[src].succ = t; + if (last_src != -1U) + { + states_[last_src].succ_tail = t - 1; + edges_[t - 1].next_succ = 0; + } + while (++last_src != src) + { + states_[last_src].succ = 0; + states_[last_src].succ_tail = 0; + } + } + else + { + edges_[t - 1].next_succ = t; + } + } if (last_src != -1U) - { - states_[last_src].succ_tail = tend - 1; - edges_[tend - 1].next_succ = 0; - } + { + states_[last_src].succ_tail = tend - 1; + edges_[tend - 1].next_succ = 0; + } unsigned send = states_.size(); while (++last_src != send) - { - states_[last_src].succ = 0; - states_[last_src].succ_tail = 0; - } + { + states_[last_src].succ = 0; + states_[last_src].succ_tail = 0; + } //std::cerr << "\nafter\n"; //dump_storage(std::cerr); } @@ -930,10 +930,10 @@ namespace spot assert(newst.size() == states_.size()); unsigned tend = edges_.size(); for (unsigned t = 1; t < tend; t++) - { - edges_[t].dst = newst[edges_[t].dst]; - edges_[t].src = newst[edges_[t].src]; - } + { + edges_[t].dst = newst[edges_[t].dst]; + edges_[t].src = newst[edges_[t].src]; + } } void defrag_states(std::vector&& newst, unsigned used_states) @@ -947,22 +947,22 @@ namespace spot // Shift all states in states_, as indicated by newst. unsigned send = states_.size(); for (state s = 0; s < send; ++s) - { - state dst = newst[s]; - if (dst == s) - continue; - if (dst == -1U) - { - // This is an erased state. Mark all its edges as - // dead (i.e., t.next_succ should point to t for each of - // them). - auto t = states_[s].succ; - while (t) - std::swap(t, edges_[t].next_succ); - continue; - } - states_[dst] = std::move(states_[s]); - } + { + state dst = newst[s]; + if (dst == s) + continue; + if (dst == -1U) + { + // This is an erased state. Mark all its edges as + // dead (i.e., t.next_succ should point to t for each of + // them). + auto t = states_[s].succ; + while (t) + std::swap(t, edges_[t].next_succ); + continue; + } + states_[dst] = std::move(states_[s]); + } states_.resize(used_states); // Shift all edges in edges_. The algorithm is @@ -972,33 +972,33 @@ namespace spot std::vector newidx(tend); unsigned dest = 1; for (edge t = 1; t < tend; ++t) - { - if (is_dead_edge(t)) - continue; - if (t != dest) - edges_[dest] = std::move(edges_[t]); - newidx[t] = dest; - ++dest; - } + { + if (is_dead_edge(t)) + continue; + if (t != dest) + edges_[dest] = std::move(edges_[t]); + newidx[t] = dest; + ++dest; + } edges_.resize(dest); killed_edge_ = 0; // Adjust next_succ and dst pointers in all edges. for (edge t = 1; t < dest; ++t) - { - auto& tr = edges_[t]; - tr.next_succ = newidx[tr.next_succ]; - tr.dst = newst[tr.dst]; - tr.src = newst[tr.src]; - assert(tr.dst != -1U); - } + { + auto& tr = edges_[t]; + tr.next_succ = newidx[tr.next_succ]; + tr.dst = newst[tr.dst]; + tr.src = newst[tr.src]; + assert(tr.dst != -1U); + } // Adjust succ and succ_tails pointers in all states. for (auto& s: states_) - { - s.succ = newidx[s.succ]; - s.succ_tail = newidx[s.succ_tail]; - } + { + s.succ = newidx[s.succ]; + s.succ_tail = newidx[s.succ_tail]; + } //std::cerr << "\nafter defrag\n"; //dump_storage(std::cerr); diff --git a/spot/graph/ngraph.hh b/spot/graph/ngraph.hh index e08b18c22..822cfb424 100644 --- a/spot/graph/ngraph.hh +++ b/spot/graph/ngraph.hh @@ -26,9 +26,9 @@ namespace spot { template , - typename Name_Equal = std::equal_to> + typename State_Name, + typename Name_Hash = std::hash, + typename Name_Equal = std::equal_to> class SPOT_API named_graph { protected: @@ -40,7 +40,7 @@ namespace spot typedef State_Name name; typedef std::unordered_map name_to_state_t; + Name_Hash, Name_Equal> name_to_state_t; name_to_state_t name_to_state; typedef std::vector state_to_name_t; state_to_name_t state_to_name; @@ -65,14 +65,14 @@ namespace spot { auto p = name_to_state.emplace(n, 0U); if (p.second) - { - unsigned s = g_.new_state(std::forward(args)...); - p.first->second = s; - if (state_to_name.size() < s + 1) - state_to_name.resize(s + 1); - state_to_name[s] = n; - return s; - } + { + unsigned s = g_.new_state(std::forward(args)...); + p.first->second = s; + if (state_to_name.size() < s + 1) + state_to_name.resize(s + 1); + state_to_name[s] = n; + return s; + } return p.first->second; } @@ -85,27 +85,27 @@ namespace spot { auto p = name_to_state.emplace(newname, s); if (!p.second) - { - // The state already exists. Change its number. - auto old = p.first->second; - p.first->second = s; - // Add the successor of OLD to those of S. - auto& trans = g_.edge_vector(); - auto& states = g_.states(); - trans[states[s].succ_tail].next_succ = states[old].succ; - states[s].succ_tail = states[old].succ_tail; - states[old].succ = 0; - states[old].succ_tail = 0; - // Remove all references to old in edges: - unsigned tend = trans.size(); - for (unsigned t = 1; t < tend; ++t) - { - if (trans[t].src == old) - trans[t].src = s; - if (trans[t].dst == old) - trans[t].dst = s; - } - } + { + // The state already exists. Change its number. + auto old = p.first->second; + p.first->second = s; + // Add the successor of OLD to those of S. + auto& trans = g_.edge_vector(); + auto& states = g_.states(); + trans[states[s].succ_tail].next_succ = states[old].succ; + states[s].succ_tail = states[old].succ_tail; + states[old].succ = 0; + states[old].succ_tail = 0; + // Remove all references to old in edges: + unsigned tend = trans.size(); + for (unsigned t = 1; t < tend; ++t) + { + if (trans[t].src == old) + trans[t].src = s; + if (trans[t].dst == old) + trans[t].dst = s; + } + } return !p.second; } @@ -134,7 +134,7 @@ namespace spot new_edge(name src, name dst, Args&&... args) { return g_.new_edge(get_state(src), get_state(dst), - std::forward(args)...); + std::forward(args)...); } template @@ -144,19 +144,19 @@ namespace spot std::vector d; d.reserve(dst.size()); for (auto n: dst) - d.push_back(get_state(n)); + d.push_back(get_state(n)); return g_.new_edge(get_state(src), d, std::forward(args)...); } template edge new_edge(name src, - const std::initializer_list& dst, Args&&... args) + const std::initializer_list& dst, Args&&... args) { std::vector d; d.reserve(dst.size()); for (auto n: dst) - d.push_back(get_state(n)); + d.push_back(get_state(n)); return g_.new_edge(get_state(src), d, std::forward(args)...); } }; diff --git a/spot/kripke/kripkegraph.hh b/spot/kripke/kripkegraph.hh index 81fe5273a..488c6891f 100644 --- a/spot/kripke/kripkegraph.hh +++ b/spot/kripke/kripkegraph.hh @@ -46,16 +46,16 @@ namespace spot // Do not simply return "other - this", it might not fit in an int. if (o < this) - return -1; + return -1; if (o > this) - return 1; + return 1; return 0; } virtual size_t hash() const override { return - reinterpret_cast(this) - static_cast(nullptr); + reinterpret_cast(this) - static_cast(nullptr); } virtual kripke_graph_state* @@ -93,7 +93,7 @@ namespace spot edge p_; public: kripke_graph_succ_iterator(const Graph* g, - const typename Graph::state_storage_t* s): + const typename Graph::state_storage_t* s): kripke_succ_iterator(s->cond()), g_(g), t_(s->succ) @@ -131,7 +131,7 @@ namespace spot { assert(!done()); return const_cast - (&g_->state_data(g_->edge_storage(p_).dst)); + (&g_->state_data(g_->edge_storage(p_).dst)); } }; @@ -176,14 +176,14 @@ namespace spot graph_t::state get_init_state_number() const { if (num_states() == 0) - const_cast(g_).new_state(); + const_cast(g_).new_state(); return init_number_; } virtual const kripke_graph_state* get_init_state() const override { if (num_states() == 0) - const_cast(g_).new_state(); + const_cast(g_).new_state(); return state_from_number(init_number_); } @@ -197,13 +197,13 @@ namespace spot assert(!s->succ || g_.valid_trans(s->succ)); if (this->iter_cache_) - { - auto it = - down_cast*>(this->iter_cache_); - it->recycle(s); - this->iter_cache_ = nullptr; - return it; - } + { + auto it = + down_cast*>(this->iter_cache_); + it->recycle(s); + this->iter_cache_ = nullptr; + return it; + } return new kripke_graph_succ_iterator(&g_, s); } diff --git a/spot/ltsmin/ltsmin.cc b/spot/ltsmin/ltsmin.cc index b84f5b980..4f9f2fe7f 100644 --- a/spot/ltsmin/ltsmin.cc +++ b/spot/ltsmin/ltsmin.cc @@ -51,13 +51,13 @@ namespace spot } transition_info_t; typedef void (*TransitionCB)(void *ctx, - transition_info_t *transition_info, - int *dst); + transition_info_t *transition_info, + int *dst); } struct spins_interface { - lt_dlhandle handle; // handle to the dynamic library + lt_dlhandle handle; // handle to the dynamic library void (*get_initial_state)(void *to); int (*have_property)(); int (*get_successors)(void* m, int *in, TransitionCB, void *arg); @@ -72,7 +72,7 @@ namespace spot ~spins_interface() { if (handle) - lt_dlclose(handle); + lt_dlclose(handle); lt_dlexit(); } }; @@ -87,46 +87,46 @@ namespace spot struct spins_state: public state { spins_state(int s, fixed_size_pool* p) - : pool(p), size(s), count(1) + : pool(p), size(s), count(1) { } void compute_hash() { - hash_value = 0; - for (int i = 0; i < size; ++i) - hash_value = wang32_hash(hash_value ^ vars[i]); + hash_value = 0; + for (int i = 0; i < size; ++i) + hash_value = wang32_hash(hash_value ^ vars[i]); } spins_state* clone() const { - ++count; - return const_cast(this); + ++count; + return const_cast(this); } void destroy() const { - if (--count) - return; - pool->deallocate(this); + if (--count) + return; + pool->deallocate(this); } size_t hash() const { - return hash_value; + return hash_value; } int compare(const state* other) const { - if (this == other) - return 0; - const spins_state* o = down_cast(other); - assert(o); - if (hash_value < o->hash_value) - return -1; - if (hash_value > o->hash_value) - return 1; - return memcmp(vars, o->vars, size * sizeof(*vars)); + if (this == other) + return 0; + const spins_state* o = down_cast(other); + assert(o); + if (hash_value < o->hash_value) + return -1; + if (hash_value > o->hash_value) + return 1; + return memcmp(vars, o->vars, size * sizeof(*vars)); } private: @@ -146,53 +146,53 @@ namespace spot struct spins_compressed_state: public state { spins_compressed_state(int s, multiple_size_pool* p) - : pool(p), size(s), count(1) + : pool(p), size(s), count(1) { } void compute_hash() { - hash_value = 0; - for (int i = 0; i < size; ++i) - hash_value = wang32_hash(hash_value ^ vars[i]); + hash_value = 0; + for (int i = 0; i < size; ++i) + hash_value = wang32_hash(hash_value ^ vars[i]); } spins_compressed_state* clone() const { - ++count; - return const_cast(this); + ++count; + return const_cast(this); } void destroy() const { - if (--count) - return; - pool->deallocate(this, sizeof(*this) + size * sizeof(*vars)); + if (--count) + return; + pool->deallocate(this, sizeof(*this) + size * sizeof(*vars)); } size_t hash() const { - return hash_value; + return hash_value; } int compare(const state* other) const { - if (this == other) - return 0; - const spins_compressed_state* o = - down_cast(other); - assert(o); - if (hash_value < o->hash_value) - return -1; - if (hash_value > o->hash_value) - return 1; + if (this == other) + return 0; + const spins_compressed_state* o = + down_cast(other); + assert(o); + if (hash_value < o->hash_value) + return -1; + if (hash_value > o->hash_value) + return 1; - if (size < o->size) - return -1; - if (size > o->size) - return 1; + if (size < o->size) + return -1; + if (size > o->size) + return 1; - return memcmp(vars, o->vars, size * sizeof(*vars)); + return memcmp(vars, o->vars, size * sizeof(*vars)); } private: @@ -223,8 +223,8 @@ namespace spot ~callback_context() { - for (auto t: transitions) - t->destroy(); + for (auto t: transitions) + t->destroy(); } }; @@ -233,7 +233,7 @@ namespace spot callback_context* ctx = static_cast(arg); fixed_size_pool* p = static_cast(ctx->pool); spins_state* out = - new(p->allocate()) spins_state(ctx->state_size, p); + new(p->allocate()) spins_state(ctx->state_size, p); memcpy(out->vars, dst, ctx->state_size * sizeof(int)); out->compute_hash(); ctx->transitions.push_back(out); @@ -248,7 +248,7 @@ namespace spot ctx->compress(dst, ctx->state_size, ctx->compressed, csize); void* mem = p->allocate(sizeof(spins_compressed_state) - + sizeof(int) * csize); + + sizeof(int) * csize); spins_compressed_state* out = new(mem) spins_compressed_state(csize, p); memcpy(out->vars, ctx->compressed, csize * sizeof(int)); out->compute_hash(); @@ -263,43 +263,43 @@ namespace spot public: spins_succ_iterator(const callback_context* cc, - bdd cond) - : kripke_succ_iterator(cond), cc_(cc) + bdd cond) + : kripke_succ_iterator(cond), cc_(cc) { } void recycle(const callback_context* cc, bdd cond) { - delete cc_; - cc_ = cc; - kripke_succ_iterator::recycle(cond); + delete cc_; + cc_ = cc; + kripke_succ_iterator::recycle(cond); } ~spins_succ_iterator() { - delete cc_; + delete cc_; } virtual bool first() override { - it_ = cc_->transitions.begin(); - return it_ != cc_->transitions.end(); + it_ = cc_->transitions.begin(); + return it_ != cc_->transitions.end(); } virtual bool next() override { - ++it_; - return it_ != cc_->transitions.end(); + ++it_; + return it_ != cc_->transitions.end(); } virtual bool done() const override { - return it_ == cc_->transitions.end(); + return it_ == cc_->transitions.end(); } virtual state* dst() const override { - return (*it_)->clone(); + return (*it_)->clone(); } private: @@ -318,7 +318,7 @@ namespace spot relop op; int val; int bddvar; // if "var_num op val" is true, output bddvar, - // else its negation + // else its negation }; typedef std::vector prop_set; @@ -332,10 +332,10 @@ namespace spot void convert_aps(const atomic_prop_set* aps, - spins_interface_ptr d, - bdd_dict_ptr dict, - formula dead, - prop_set& out) + spins_interface_ptr d, + bdd_dict_ptr dict, + formula dead, + prop_set& out) { int errors = 0; std::ostringstream err; @@ -345,257 +345,257 @@ namespace spot val_map_t val_map; for (int i = 0; i < state_size; ++i) - { - const char* name = d->get_state_variable_name(i); - int type = d->get_state_variable_type(i); - var_info v = { i , type }; - val_map[name] = v; - } + { + const char* name = d->get_state_variable_name(i); + int type = d->get_state_variable_type(i); + var_info v = { i , type }; + val_map[name] = v; + } int type_count = d->get_type_count(); typedef std::map enum_map_t; std::vector enum_map(type_count); for (int i = 0; i < type_count; ++i) - { - int enum_count = d->get_type_value_count(i); - for (int j = 0; j < enum_count; ++j) - enum_map[i].emplace(d->get_type_value_name(i, j), j); - } + { + int enum_count = d->get_type_value_count(i); + for (int j = 0; j < enum_count; ++j) + enum_map[i].emplace(d->get_type_value_name(i, j), j); + } for (atomic_prop_set::const_iterator ap = aps->begin(); - ap != aps->end(); ++ap) - { - if (*ap == dead) - continue; + ap != aps->end(); ++ap) + { + if (*ap == dead) + continue; - const std::string& str = ap->ap_name(); - const char* s = str.c_str(); + const std::string& str = ap->ap_name(); + const char* s = str.c_str(); - // Skip any leading blank. - while (*s && (*s == ' ' || *s == '\t')) - ++s; - if (!*s) - { - err << "Proposition `" << str << "' cannot be parsed.\n"; - ++errors; - continue; - } + // Skip any leading blank. + while (*s && (*s == ' ' || *s == '\t')) + ++s; + if (!*s) + { + err << "Proposition `" << str << "' cannot be parsed.\n"; + ++errors; + continue; + } - char* name = (char*) malloc(str.size() + 1); - char* name_p = name; - char* lastdot = nullptr; - while (*s && (*s != '=') && *s != '<' && *s != '!' && *s != '>') - { + char* name = (char*) malloc(str.size() + 1); + char* name_p = name; + char* lastdot = nullptr; + while (*s && (*s != '=') && *s != '<' && *s != '!' && *s != '>') + { - if (*s == ' ' || *s == '\t') - ++s; - else - { - if (*s == '.') - lastdot = name_p; - *name_p++ = *s++; - } - } - *name_p = 0; + if (*s == ' ' || *s == '\t') + ++s; + else + { + if (*s == '.') + lastdot = name_p; + *name_p++ = *s++; + } + } + *name_p = 0; - if (name == name_p) - { - err << "Proposition `" << str << "' cannot be parsed.\n"; - free(name); - ++errors; - continue; - } + if (name == name_p) + { + err << "Proposition `" << str << "' cannot be parsed.\n"; + free(name); + ++errors; + continue; + } - // Lookup the name - val_map_t::const_iterator ni = val_map.find(name); - if (ni == val_map.end()) - { - // We may have a name such as X.Y.Z - // If it is not a known variable, it might mean - // an enumerated variable X.Y with value Z. - if (lastdot) - { - *lastdot++ = 0; - ni = val_map.find(name); - } + // Lookup the name + val_map_t::const_iterator ni = val_map.find(name); + if (ni == val_map.end()) + { + // We may have a name such as X.Y.Z + // If it is not a known variable, it might mean + // an enumerated variable X.Y with value Z. + if (lastdot) + { + *lastdot++ = 0; + ni = val_map.find(name); + } - if (ni == val_map.end()) - { - err << "No variable `" << name - << "' found in model (for proposition `" - << str << "').\n"; - free(name); - ++errors; - continue; - } + if (ni == val_map.end()) + { + err << "No variable `" << name + << "' found in model (for proposition `" + << str << "').\n"; + free(name); + ++errors; + continue; + } - // We have found the enumerated variable, and lastdot is - // pointing to its expected value. - int type_num = ni->second.type; - enum_map_t::const_iterator ei = enum_map[type_num].find(lastdot); - if (ei == enum_map[type_num].end()) - { - err << "No state `" << lastdot << "' known for variable `" - << name << "'.\n"; - err << "Possible states are:"; - for (auto& ej: enum_map[type_num]) - err << ' ' << ej.first; - err << '\n'; + // We have found the enumerated variable, and lastdot is + // pointing to its expected value. + int type_num = ni->second.type; + enum_map_t::const_iterator ei = enum_map[type_num].find(lastdot); + if (ei == enum_map[type_num].end()) + { + err << "No state `" << lastdot << "' known for variable `" + << name << "'.\n"; + err << "Possible states are:"; + for (auto& ej: enum_map[type_num]) + err << ' ' << ej.first; + err << '\n'; - free(name); - ++errors; - continue; - } + free(name); + ++errors; + continue; + } - // At this point, *s should be 0. - if (*s) - { - err << "Trailing garbage `" << s - << "' at end of proposition `" - << str << "'.\n"; - free(name); - ++errors; - continue; - } + // At this point, *s should be 0. + if (*s) + { + err << "Trailing garbage `" << s + << "' at end of proposition `" + << str << "'.\n"; + free(name); + ++errors; + continue; + } - // Record that X.Y must be equal to Z. - int v = dict->register_proposition(*ap, d.get()); - one_prop p = { ni->second.num, OP_EQ, ei->second, v }; - out.push_back(p); - free(name); - continue; - } + // Record that X.Y must be equal to Z. + int v = dict->register_proposition(*ap, d.get()); + one_prop p = { ni->second.num, OP_EQ, ei->second, v }; + out.push_back(p); + free(name); + continue; + } - int var_num = ni->second.num; + int var_num = ni->second.num; - if (!*s) // No operator? Assume "!= 0". - { - int v = dict->register_proposition(*ap, d); - one_prop p = { var_num, OP_NE, 0, v }; - out.push_back(p); - free(name); - continue; - } + if (!*s) // No operator? Assume "!= 0". + { + int v = dict->register_proposition(*ap, d); + one_prop p = { var_num, OP_NE, 0, v }; + out.push_back(p); + free(name); + continue; + } - relop op; + relop op; - switch (*s) - { - case '!': - if (s[1] != '=') - goto report_error; - op = OP_NE; - s += 2; - break; - case '=': - if (s[1] != '=') - goto report_error; - op = OP_EQ; - s += 2; - break; - case '<': - if (s[1] == '=') - { - op = OP_LE; - s += 2; - } - else - { - op = OP_LT; - ++s; - } - break; - case '>': - if (s[1] == '=') - { - op = OP_GE; - s += 2; - } - else - { - op = OP_GT; - ++s; - } - break; - default: - report_error: - err << "Unexpected `" << s - << "' while parsing atomic proposition `" << str - << "'.\n"; - ++errors; - free(name); - continue; - } + switch (*s) + { + case '!': + if (s[1] != '=') + goto report_error; + op = OP_NE; + s += 2; + break; + case '=': + if (s[1] != '=') + goto report_error; + op = OP_EQ; + s += 2; + break; + case '<': + if (s[1] == '=') + { + op = OP_LE; + s += 2; + } + else + { + op = OP_LT; + ++s; + } + break; + case '>': + if (s[1] == '=') + { + op = OP_GE; + s += 2; + } + else + { + op = OP_GT; + ++s; + } + break; + default: + report_error: + err << "Unexpected `" << s + << "' while parsing atomic proposition `" << str + << "'.\n"; + ++errors; + free(name); + continue; + } - while (*s && (*s == ' ' || *s == '\t')) - ++s; + while (*s && (*s == ' ' || *s == '\t')) + ++s; - int val = 0; // Initialize to kill a warning from old compilers. - int type_num = ni->second.type; - if (type_num == 0 || (*s >= '0' && *s <= '9') || *s == '-') - { - char* s_end; - val = strtol(s, &s_end, 10); - if (s == s_end) - { - err << "Failed to parse `" << s << "' as an integer.\n"; - ++errors; - free(name); - continue; - } - s = s_end; - } - else - { - // We are in a case such as P_0 == S, trying to convert - // the string S into an integer. - const char* end = s; - while (*end && *end != ' ' && *end != '\t') - ++end; - std::string st(s, end); + int val = 0; // Initialize to kill a warning from old compilers. + int type_num = ni->second.type; + if (type_num == 0 || (*s >= '0' && *s <= '9') || *s == '-') + { + char* s_end; + val = strtol(s, &s_end, 10); + if (s == s_end) + { + err << "Failed to parse `" << s << "' as an integer.\n"; + ++errors; + free(name); + continue; + } + s = s_end; + } + else + { + // We are in a case such as P_0 == S, trying to convert + // the string S into an integer. + const char* end = s; + while (*end && *end != ' ' && *end != '\t') + ++end; + std::string st(s, end); - // Lookup the string. - enum_map_t::const_iterator ei = enum_map[type_num].find(st); - if (ei == enum_map[type_num].end()) - { - err << "No state `" << st << "' known for variable `" - << name << "'.\n"; - err << "Possible states are:"; - for (ei = enum_map[type_num].begin(); - ei != enum_map[type_num].end(); ++ei) - err << ' ' << ei->first; - err << '\n'; + // Lookup the string. + enum_map_t::const_iterator ei = enum_map[type_num].find(st); + if (ei == enum_map[type_num].end()) + { + err << "No state `" << st << "' known for variable `" + << name << "'.\n"; + err << "Possible states are:"; + for (ei = enum_map[type_num].begin(); + ei != enum_map[type_num].end(); ++ei) + err << ' ' << ei->first; + err << '\n'; - free(name); - ++errors; - continue; - } - s = end; - val = ei->second; - } + free(name); + ++errors; + continue; + } + s = end; + val = ei->second; + } - free(name); + free(name); - while (*s && (*s == ' ' || *s == '\t')) - ++s; - if (*s) - { - err << "Unexpected `" << s - << "' while parsing atomic proposition `" << str - << "'.\n"; - ++errors; - continue; - } + while (*s && (*s == ' ' || *s == '\t')) + ++s; + if (*s) + { + err << "Unexpected `" << s + << "' while parsing atomic proposition `" << str + << "'.\n"; + ++errors; + continue; + } - int v = dict->register_proposition(*ap, d); - one_prop p = { var_num, op, val, v }; - out.push_back(p); - } + int v = dict->register_proposition(*ap, d); + one_prop p = { var_num, op, val, v }; + out.push_back(p); + } if (errors) - throw std::runtime_error(err.str()); + throw std::runtime_error(err.str()); } //////////////////////////////////////////////////////////////////////// @@ -606,308 +606,308 @@ namespace spot public: spins_kripke(spins_interface_ptr d, const bdd_dict_ptr& dict, - const spot::prop_set* ps, formula dead, - int compress) - : kripke(dict), - d_(d), - state_size_(d_->get_state_size()), - ps_(ps), - compress_(compress == 0 ? nullptr - : compress == 1 ? int_array_array_compress - : int_array_array_compress2), - decompress_(compress == 0 ? nullptr - : compress == 1 ? int_array_array_decompress - : int_array_array_decompress2), - uncompressed_(compress ? new int[state_size_ + 30] : nullptr), - compressed_(compress ? new int[state_size_ * 2] : nullptr), - statepool_(compress ? sizeof(spins_compressed_state) : - (sizeof(spins_state) + state_size_ * sizeof(int))), - state_condition_last_state_(nullptr), - state_condition_last_cc_(nullptr) + const spot::prop_set* ps, formula dead, + int compress) + : kripke(dict), + d_(d), + state_size_(d_->get_state_size()), + ps_(ps), + compress_(compress == 0 ? nullptr + : compress == 1 ? int_array_array_compress + : int_array_array_compress2), + decompress_(compress == 0 ? nullptr + : compress == 1 ? int_array_array_decompress + : int_array_array_decompress2), + uncompressed_(compress ? new int[state_size_ + 30] : nullptr), + compressed_(compress ? new int[state_size_ * 2] : nullptr), + statepool_(compress ? sizeof(spins_compressed_state) : + (sizeof(spins_state) + state_size_ * sizeof(int))), + state_condition_last_state_(nullptr), + state_condition_last_cc_(nullptr) { - vname_ = new const char*[state_size_]; - format_filter_ = new bool[state_size_]; - for (int i = 0; i < state_size_; ++i) - { - vname_[i] = d_->get_state_variable_name(i); - // We don't want to print variables that can take a single - // value (e.g. process with a single state) to shorten the - // output. - int type = d->get_state_variable_type(i); - format_filter_[i] = - (d->get_type_value_count(type) != 1); - } + vname_ = new const char*[state_size_]; + format_filter_ = new bool[state_size_]; + for (int i = 0; i < state_size_; ++i) + { + vname_[i] = d_->get_state_variable_name(i); + // We don't want to print variables that can take a single + // value (e.g. process with a single state) to shorten the + // output. + int type = d->get_state_variable_type(i); + format_filter_[i] = + (d->get_type_value_count(type) != 1); + } - // Register the "dead" proposition. There are three cases to - // consider: - // * If DEAD is "false", it means we are not interested in finite - // sequences of the system. - // * If DEAD is "true", we want to check finite sequences as well - // as infinite sequences, but do not need to distinguish them. - // * If DEAD is any other string, this is the name a property - // that should be true when looping on a dead state, and false - // otherwise. - // We handle these three cases by setting ALIVE_PROP and DEAD_PROP - // appropriately. ALIVE_PROP is the bdd that should be ANDed - // to all transitions leaving a live state, while DEAD_PROP should - // be ANDed to all transitions leaving a dead state. - if (dead.is_ff()) - { - alive_prop = bddtrue; - dead_prop = bddfalse; - } - else if (dead.is_tt()) - { - alive_prop = bddtrue; - dead_prop = bddtrue; - } - else - { - int var = dict->register_proposition(dead, d_); - dead_prop = bdd_ithvar(var); - alive_prop = bdd_nithvar(var); - } + // Register the "dead" proposition. There are three cases to + // consider: + // * If DEAD is "false", it means we are not interested in finite + // sequences of the system. + // * If DEAD is "true", we want to check finite sequences as well + // as infinite sequences, but do not need to distinguish them. + // * If DEAD is any other string, this is the name a property + // that should be true when looping on a dead state, and false + // otherwise. + // We handle these three cases by setting ALIVE_PROP and DEAD_PROP + // appropriately. ALIVE_PROP is the bdd that should be ANDed + // to all transitions leaving a live state, while DEAD_PROP should + // be ANDed to all transitions leaving a dead state. + if (dead.is_ff()) + { + alive_prop = bddtrue; + dead_prop = bddfalse; + } + else if (dead.is_tt()) + { + alive_prop = bddtrue; + dead_prop = bddtrue; + } + else + { + int var = dict->register_proposition(dead, d_); + dead_prop = bdd_ithvar(var); + alive_prop = bdd_nithvar(var); + } } ~spins_kripke() { - if (iter_cache_) - { - delete iter_cache_; - iter_cache_ = nullptr; - } - delete[] format_filter_; - delete[] vname_; - if (compress_) - { - delete[] uncompressed_; - delete[] compressed_; - } - dict_->unregister_all_my_variables(d_.get()); + if (iter_cache_) + { + delete iter_cache_; + iter_cache_ = nullptr; + } + delete[] format_filter_; + delete[] vname_; + if (compress_) + { + delete[] uncompressed_; + delete[] compressed_; + } + dict_->unregister_all_my_variables(d_.get()); - delete ps_; + delete ps_; - if (state_condition_last_state_) - state_condition_last_state_->destroy(); - delete state_condition_last_cc_; // Might be 0 already. + if (state_condition_last_state_) + state_condition_last_state_->destroy(); + delete state_condition_last_cc_; // Might be 0 already. } virtual state* get_init_state() const override { - if (compress_) - { - d_->get_initial_state(uncompressed_); - size_t csize = state_size_ * 2; - compress_(uncompressed_, state_size_, compressed_, csize); + if (compress_) + { + d_->get_initial_state(uncompressed_); + size_t csize = state_size_ * 2; + compress_(uncompressed_, state_size_, compressed_, csize); - multiple_size_pool* p = - const_cast(&compstatepool_); - void* mem = p->allocate(sizeof(spins_compressed_state) - + sizeof(int) * csize); - spins_compressed_state* res = new(mem) - spins_compressed_state(csize, p); - memcpy(res->vars, compressed_, csize * sizeof(int)); - res->compute_hash(); - return res; - } - else - { - fixed_size_pool* p = const_cast(&statepool_); - spins_state* res = new(p->allocate()) spins_state(state_size_, p); - d_->get_initial_state(res->vars); - res->compute_hash(); - return res; - } + multiple_size_pool* p = + const_cast(&compstatepool_); + void* mem = p->allocate(sizeof(spins_compressed_state) + + sizeof(int) * csize); + spins_compressed_state* res = new(mem) + spins_compressed_state(csize, p); + memcpy(res->vars, compressed_, csize * sizeof(int)); + res->compute_hash(); + return res; + } + else + { + fixed_size_pool* p = const_cast(&statepool_); + spins_state* res = new(p->allocate()) spins_state(state_size_, p); + d_->get_initial_state(res->vars); + res->compute_hash(); + return res; + } } bdd compute_state_condition_aux(const int* vars) const { - bdd res = bddtrue; - for (auto& i: *ps_) - { - int l = vars[i.var_num]; - int r = i.val; + bdd res = bddtrue; + for (auto& i: *ps_) + { + int l = vars[i.var_num]; + int r = i.val; - bool cond = false; - switch (i.op) - { - case OP_EQ: - cond = (l == r); - break; - case OP_NE: - cond = (l != r); - break; - case OP_LT: - cond = (l < r); - break; - case OP_GT: - cond = (l > r); - break; - case OP_LE: - cond = (l <= r); - break; - case OP_GE: - cond = (l >= r); - break; - } + bool cond = false; + switch (i.op) + { + case OP_EQ: + cond = (l == r); + break; + case OP_NE: + cond = (l != r); + break; + case OP_LT: + cond = (l < r); + break; + case OP_GT: + cond = (l > r); + break; + case OP_LE: + cond = (l <= r); + break; + case OP_GE: + cond = (l >= r); + break; + } - if (cond) - res &= bdd_ithvar(i.bddvar); - else - res &= bdd_nithvar(i.bddvar); - } - return res; + if (cond) + res &= bdd_ithvar(i.bddvar); + else + res &= bdd_nithvar(i.bddvar); + } + return res; } callback_context* build_cc(const int* vars, int& t) const { - callback_context* cc = new callback_context; - cc->state_size = state_size_; - cc->pool = - const_cast(compress_ - ? static_cast(&compstatepool_) - : static_cast(&statepool_)); - cc->compress = compress_; - cc->compressed = compressed_; - t = d_->get_successors(nullptr, const_cast(vars), - compress_ - ? transition_callback_compress - : transition_callback, - cc); - assert((unsigned)t == cc->transitions.size()); - return cc; + callback_context* cc = new callback_context; + cc->state_size = state_size_; + cc->pool = + const_cast(compress_ + ? static_cast(&compstatepool_) + : static_cast(&statepool_)); + cc->compress = compress_; + cc->compressed = compressed_; + t = d_->get_successors(nullptr, const_cast(vars), + compress_ + ? transition_callback_compress + : transition_callback, + cc); + assert((unsigned)t == cc->transitions.size()); + return cc; } bdd compute_state_condition(const state* st) const { - // If we just computed it, don't do it twice. - if (st == state_condition_last_state_) - return state_condition_last_cond_; + // If we just computed it, don't do it twice. + if (st == state_condition_last_state_) + return state_condition_last_cond_; - if (state_condition_last_state_) - { - state_condition_last_state_->destroy(); - delete state_condition_last_cc_; // Might be 0 already. - state_condition_last_cc_ = nullptr; - } + if (state_condition_last_state_) + { + state_condition_last_state_->destroy(); + delete state_condition_last_cc_; // Might be 0 already. + state_condition_last_cc_ = nullptr; + } - const int* vars = get_vars(st); + const int* vars = get_vars(st); - bdd res = compute_state_condition_aux(vars); - int t; - callback_context* cc = build_cc(vars, t); + bdd res = compute_state_condition_aux(vars); + int t; + callback_context* cc = build_cc(vars, t); - if (t) - { - res &= alive_prop; - } - else - { - res &= dead_prop; + if (t) + { + res &= alive_prop; + } + else + { + res &= dead_prop; - // Add a self-loop to dead-states if we care about these. - if (res != bddfalse) - cc->transitions.push_back(st->clone()); - } + // Add a self-loop to dead-states if we care about these. + if (res != bddfalse) + cc->transitions.push_back(st->clone()); + } - state_condition_last_cc_ = cc; - state_condition_last_cond_ = res; - state_condition_last_state_ = st->clone(); + state_condition_last_cc_ = cc; + state_condition_last_cond_ = res; + state_condition_last_state_ = st->clone(); - return res; + return res; } const int* get_vars(const state* st) const { - const int* vars; - if (compress_) - { - const spins_compressed_state* s = - down_cast(st); - assert(s); + const int* vars; + if (compress_) + { + const spins_compressed_state* s = + down_cast(st); + assert(s); - decompress_(s->vars, s->size, uncompressed_, state_size_); - vars = uncompressed_; - } - else - { - const spins_state* s = down_cast(st); - assert(s); - vars = s->vars; - } - return vars; + decompress_(s->vars, s->size, uncompressed_, state_size_); + vars = uncompressed_; + } + else + { + const spins_state* s = down_cast(st); + assert(s); + vars = s->vars; + } + return vars; } virtual spins_succ_iterator* succ_iter(const state* st) const override { - // This may also compute successors in state_condition_last_cc - bdd scond = compute_state_condition(st); + // This may also compute successors in state_condition_last_cc + bdd scond = compute_state_condition(st); - callback_context* cc; - if (state_condition_last_cc_) - { - cc = state_condition_last_cc_; - state_condition_last_cc_ = nullptr; // Now owned by the iterator. - } - else - { - int t; - cc = build_cc(get_vars(st), t); + callback_context* cc; + if (state_condition_last_cc_) + { + cc = state_condition_last_cc_; + state_condition_last_cc_ = nullptr; // Now owned by the iterator. + } + else + { + int t; + cc = build_cc(get_vars(st), t); - // Add a self-loop to dead-states if we care about these. - if (t == 0 && scond != bddfalse) - cc->transitions.push_back(st->clone()); - } + // Add a self-loop to dead-states if we care about these. + if (t == 0 && scond != bddfalse) + cc->transitions.push_back(st->clone()); + } - if (iter_cache_) - { - spins_succ_iterator* it = - down_cast(iter_cache_); - it->recycle(cc, scond); - iter_cache_ = nullptr; - return it; - } - return new spins_succ_iterator(cc, scond); + if (iter_cache_) + { + spins_succ_iterator* it = + down_cast(iter_cache_); + it->recycle(cc, scond); + iter_cache_ = nullptr; + return it; + } + return new spins_succ_iterator(cc, scond); } virtual bdd state_condition(const state* st) const override { - return compute_state_condition(st); + return compute_state_condition(st); } virtual std::string format_state(const state *st) const override { - const int* vars = get_vars(st); + const int* vars = get_vars(st); - std::stringstream res; + std::stringstream res; - if (state_size_ == 0) - return "empty state"; + if (state_size_ == 0) + return "empty state"; - int i = 0; - for (;;) - { - if (!format_filter_[i]) - { - ++i; - if (i == state_size_) - break; - continue; - } - res << vname_[i] << '=' << vars[i]; - ++i; - if (i == state_size_) - break; - res << ", "; - } - return res.str(); + int i = 0; + for (;;) + { + if (!format_filter_[i]) + { + ++i; + if (i == state_size_) + break; + continue; + } + res << vname_[i] << '=' << vars[i]; + ++i; + if (i == state_size_) + break; + res << ", "; + } + return res.str(); } private: @@ -949,25 +949,25 @@ namespace spot std::string compiled_ext; if (ext == ".prom" || ext == ".pm" || ext == ".pml") - { - command = "spins " + filename; - compiled_ext = ".spins"; - } + { + command = "spins " + filename; + compiled_ext = ".spins"; + } else if (ext == ".dve") - { - command = "divine compile --ltsmin " + filename; - compiled_ext = "2C"; - } + { + command = "divine compile --ltsmin " + filename; + compiled_ext = "2C"; + } else - { - throw std::runtime_error(std::string("Unknown extension '") - + ext + "'. Use '.prom', '.pm', '.pml', " - "'.dve', '.dve2C', or '.prom.spins'."); - } + { + throw std::runtime_error(std::string("Unknown extension '") + + ext + "'. Use '.prom', '.pm', '.pml', " + "'.dve', '.dve2C', or '.prom.spins'."); + } struct stat s; if (stat(filename.c_str(), &s) != 0) - throw std::runtime_error(std::string("Cannot open ") + filename); + throw std::runtime_error(std::string("Cannot open ") + filename); std::string old = filename; filename += compiled_ext; @@ -976,19 +976,19 @@ namespace spot // be compiled in the current directory. size_t pos = filename.find_last_of("/\\"); if (pos != std::string::npos) - filename = "./" + filename.substr(pos + 1); + filename = "./" + filename.substr(pos + 1); struct stat d; if (stat(filename.c_str(), &d) == 0) - if (s.st_mtime < d.st_mtime) - // The .spins or .dve2C is up-to-date, no need to recompile it. - return; + if (s.st_mtime < d.st_mtime) + // The .spins or .dve2C is up-to-date, no need to recompile it. + return; int res = system(command.c_str()); if (res) - throw std::runtime_error(std::string("Execution of '") - + command.c_str() + "' returned exit code " - + std::to_string(WEXITSTATUS(res))); + throw std::runtime_error(std::string("Execution of '") + + command.c_str() + "' returned exit code " + + std::to_string(WEXITSTATUS(res))); } } @@ -1012,9 +1012,9 @@ namespace spot lt_dlhandle h = lt_dlopen(file.c_str()); if (!h) { - lt_dlexit(); - throw std::runtime_error(std::string("Failed to load '") - + file + "'."); + lt_dlexit(); + throw std::runtime_error(std::string("Failed to load '") + + file + "'."); } auto d = std::make_shared(); @@ -1068,20 +1068,20 @@ namespace spot } if (!(d->get_initial_state - && d->get_successors - && d->get_state_size - && d->get_state_variable_name - && d->get_state_variable_type - && d->get_type_count - && d->get_type_name - && d->get_type_value_count - && d->get_type_value_name)) + && d->get_successors + && d->get_state_size + && d->get_state_variable_name + && d->get_state_variable_type + && d->get_type_count + && d->get_type_name + && d->get_type_value_count + && d->get_type_value_name)) throw std::runtime_error(std::string("Failed resolve some symbol" - "while loading '") + file + "'."); + "while loading '") + file + "'."); if (d->have_property && d->have_property()) throw std::runtime_error("Models with embedded properties " - "are not supported."); + "are not supported."); return { d }; } @@ -1089,19 +1089,19 @@ namespace spot kripke_ptr ltsmin_model::kripke(const atomic_prop_set* to_observe, - bdd_dict_ptr dict, - const formula dead, int compress) const + bdd_dict_ptr dict, + const formula dead, int compress) const { spot::prop_set* ps = new spot::prop_set; try { - convert_aps(to_observe, iface, dict, dead, *ps); + convert_aps(to_observe, iface, dict, dead, *ps); } catch (std::runtime_error) { - delete ps; - dict->unregister_all_my_variables(iface.get()); - throw; + delete ps; + dict->unregister_all_my_variables(iface.get()); + throw; } return std::make_shared(iface, dict, ps, dead, compress); diff --git a/spot/ltsmin/ltsmin.hh b/spot/ltsmin/ltsmin.hh index fc9a6df3b..87a3034dc 100644 --- a/spot/ltsmin/ltsmin.hh +++ b/spot/ltsmin/ltsmin.hh @@ -67,9 +67,9 @@ namespace spot // to enable compression, 2 to enable a faster compression that only // work if all variables are smaller than 2^28. kripke_ptr kripke(const atomic_prop_set* to_observe, - bdd_dict_ptr dict, - formula dead = formula::tt(), - int compress = 0) const; + bdd_dict_ptr dict, + formula dead = formula::tt(), + int compress = 0) const; /// Number of variables in a state int state_size() const; diff --git a/spot/misc/bareword.cc b/spot/misc/bareword.cc index 144242012..91a259a2f 100644 --- a/spot/misc/bareword.cc +++ b/spot/misc/bareword.cc @@ -32,12 +32,12 @@ namespace spot { // Bare words cannot be empty and should start with a letter. if (!*str - || !(isalpha(*str) || *str == '_' || *str == '.')) + || !(isalpha(*str) || *str == '_' || *str == '.')) return false; // The remaining of the word must be alphanumeric. while (*++str) if (!(isalnum(*str) || *str == '_' || *str == '.')) - return false; + return false; return true; } @@ -58,7 +58,7 @@ namespace spot return false; while (*++str) if (!(isalnum(*str) || *str == '_')) - return false; + return false; return true; } diff --git a/spot/misc/bitvect.cc b/spot/misc/bitvect.cc index 667738f3b..021c3eecf 100644 --- a/spot/misc/bitvect.cc +++ b/spot/misc/bitvect.cc @@ -39,7 +39,7 @@ namespace spot const size_t bpb = 8 * sizeof(bitvect::block_t); size_t n = (bitcount + bpb - 1) / bpb; if (n < 1) - return 1; + return 1; return n; } @@ -60,12 +60,12 @@ namespace spot { static unsigned long init() { - return 14695981039346656037UL; + return 14695981039346656037UL; } static unsigned long prime() { - return 1099511628211UL; + return 1099511628211UL; } }; #endif @@ -76,12 +76,12 @@ namespace spot { static unsigned long init() { - return 2166136261UL; + return 2166136261UL; } static unsigned long prime() { - return 16777619UL; + return 16777619UL; } }; @@ -109,7 +109,7 @@ namespace spot // already contains one int of local_storage_, but // we allocate n-1 more so that we store the table. void* mem = operator new(sizeof(bitvect) - + (n - 1) * sizeof(bitvect::block_t)); + + (n - 1) * sizeof(bitvect::block_t)); bitvect* res = new(mem) bitvect(size_, n, true); memcpy(res->storage_, storage_, res->block_count_ * sizeof(block_t)); return res; @@ -125,8 +125,8 @@ namespace spot return res; for (i = 0; i < m - 1; ++i) { - res ^= storage_[i]; - res *= fnv::prime(); + res ^= storage_[i]; + res *= fnv::prime(); } // Deal with the last block, that might not be fully used. // Compute the number n of bits used in the last block. @@ -144,7 +144,7 @@ namespace spot // already contains one int of local_storage_, but // we allocate n-1 more so that we store the table. void* mem = operator new(sizeof(bitvect) - + (n - 1) * sizeof(bitvect::block_t)); + + (n - 1) * sizeof(bitvect::block_t)); return new(mem) bitvect(bitcount, n); } @@ -176,16 +176,16 @@ namespace spot size_t end = a.size(); if (end == 0) { - os << "empty\n"; - return os; + os << "empty\n"; + return os; } int w = floor(log10(end - 1)) + 1; for (size_t i = 0; i != end; ++i) { - os.width(w); - os << i; - os.width(1); - os << ": " << a.at(i) << '\n'; + os.width(w); + os << i; + os.width(1); + os << ": " << a.at(i) << '\n'; } return os; } diff --git a/spot/misc/bitvect.hh b/spot/misc/bitvect.hh index 0d32db835..ac9175893 100644 --- a/spot/misc/bitvect.hh +++ b/spot/misc/bitvect.hh @@ -44,7 +44,7 @@ namespace spot /// /// The resulting bitvect_array should be released with delete. SPOT_API bitvect_array* make_bitvect_array(size_t bitcount, - size_t vectcount); + size_t vectcount); /// \brief A bit vector class SPOT_API bitvect @@ -85,14 +85,14 @@ namespace spot reserve_blocks(other.block_count_); size_ = other.size(); for (size_t i = 0; i < block_count_; ++i) - storage_[i] = other.storage_[i]; + storage_[i] = other.storage_[i]; return *this; } ~bitvect() { if (storage_ != &local_storage_) - free(storage_); + free(storage_); } /// Grow the bitvector to \a new_block_count blocks. @@ -101,20 +101,20 @@ namespace spot void reserve_blocks(size_t new_block_count) { if (new_block_count < block_count_) - return; + return; if (storage_ == &local_storage_) - { - block_t* new_storage_ = static_cast - (malloc(new_block_count * sizeof(block_t))); - for (size_t i = 0; i < block_count_; ++i) - new_storage_[i] = storage_[i]; - storage_ = new_storage_; - } + { + block_t* new_storage_ = static_cast + (malloc(new_block_count * sizeof(block_t))); + for (size_t i = 0; i < block_count_; ++i) + new_storage_[i] = storage_[i]; + storage_ = new_storage_; + } else - { - storage_ = static_cast - (realloc(storage_, new_block_count * sizeof(block_t))); - } + { + storage_ = static_cast + (realloc(storage_, new_block_count * sizeof(block_t))); + } block_count_ = new_block_count; } @@ -137,44 +137,44 @@ namespace spot void push_back(bool val) { if (size() == capacity()) - grow(); + grow(); size_t pos = size_++; if (val) - set(pos); + set(pos); else - clear(pos); + clear(pos); } /// \brief Append the lowest \a count bits of \a data. void push_back(block_t data, unsigned count) { if (size() + count > capacity()) - grow(); + grow(); const size_t bpb = 8 * sizeof(block_t); // Clear the higher bits. if (count != bpb) - data &= (1UL << count) - 1; + data &= (1UL << count) - 1; size_t n = size() % bpb; size_t i = size_ / bpb; size_ += count; - if (n == 0) // Aligned on block_t boundary - { - storage_[i] = data; - } - else // Only (bpb-n) bits free in this block. - { - // Take the lower bpb-n bits of data... - block_t mask = (1UL << (bpb - n)) - 1; - block_t data1 = (data & mask) << n; - mask <<= n; - // ... write them on the higher bpb-n bits of last block. - storage_[i] = (storage_[i] & ~mask) | data1; - // Write the remaining bits in the next block. - if (bpb - n < count) - storage_[i + 1] = data >> (bpb - n); - } + if (n == 0) // Aligned on block_t boundary + { + storage_[i] = data; + } + else // Only (bpb-n) bits free in this block. + { + // Take the lower bpb-n bits of data... + block_t mask = (1UL << (bpb - n)) - 1; + block_t data1 = (data & mask) << n; + mask <<= n; + // ... write them on the higher bpb-n bits of last block. + storage_[i] = (storage_[i] & ~mask) | data1; + // Write the remaining bits in the next block. + if (bpb - n < count) + storage_[i + 1] = data >> (bpb - n); + } } size_t size() const @@ -199,7 +199,7 @@ namespace spot void clear_all() { for (size_t i = 0; i < block_count_; ++i) - storage_[i] = 0; + storage_[i] = 0; } bool is_fully_clear() const @@ -208,12 +208,12 @@ namespace spot const size_t bpb = 8 * sizeof(bitvect::block_t); size_t rest = size() % bpb; for (i = 0; i < block_count_ - !!rest; ++i) - if (storage_[i] != 0) - return false; + if (storage_[i] != 0) + return false; // The last block might not be fully used, compare only the // relevant portion. if (!rest) - return true; + return true; block_t mask = (1UL << rest) - 1; return (storage_[i] & mask) == 0; } @@ -224,10 +224,10 @@ namespace spot const size_t bpb = 8 * sizeof(bitvect::block_t); size_t rest = size() % bpb; for (i = 0; i < block_count_ - !!rest; ++i) - if (storage_[i] != -1UL) - return false; + if (storage_[i] != -1UL) + return false; if (!rest) - return true; + return true; // The last block might not be fully used, compare only the // relevant portion. block_t mask = (1UL << rest) - 1; @@ -237,13 +237,13 @@ namespace spot void set_all() { for (size_t i = 0; i < block_count_; ++i) - storage_[i] = -1UL; + storage_[i] = -1UL; } void flip_all() { for (size_t i = 0; i < block_count_; ++i) - storage_[i] = ~storage_[i]; + storage_[i] = ~storage_[i]; } void set(size_t pos) @@ -273,7 +273,7 @@ namespace spot assert(other.size_ <= size_); unsigned m = std::min(other.block_count_, block_count_); for (size_t i = 0; i < m; ++i) - storage_[i] |= other.storage_[i]; + storage_[i] |= other.storage_[i]; return *this; } @@ -282,7 +282,7 @@ namespace spot assert(other.size_ <= size_); unsigned m = std::min(other.block_count_, block_count_); for (size_t i = 0; i < m; ++i) - storage_[i] &= other.storage_[i]; + storage_[i] &= other.storage_[i]; return *this; } @@ -291,7 +291,7 @@ namespace spot assert(other.size_ <= size_); unsigned m = std::min(other.block_count_, block_count_); for (size_t i = 0; i < m; ++i) - storage_[i] ^= other.storage_[i]; + storage_[i] ^= other.storage_[i]; return *this; } @@ -299,7 +299,7 @@ namespace spot { assert(other.block_count_ <= block_count_); for (size_t i = 0; i < other.block_count_; ++i) - storage_[i] &= ~other.storage_[i]; + storage_[i] &= ~other.storage_[i]; return *this; } @@ -311,33 +311,33 @@ namespace spot const size_t bpb = 8 * sizeof(bitvect::block_t); size_t rest = size() % bpb; for (i = 0; i < block_count_ - !!rest; ++i) - if ((storage_[i] & other.storage_[i]) != other.storage_[i]) - return false; + if ((storage_[i] & other.storage_[i]) != other.storage_[i]) + return false; if (!rest) - return true; + return true; // The last block might not be fully used, compare only the // relevant portion. block_t mask = (1UL << rest) - 1; return ((storage_[i] & mask & other.storage_[i]) - == (other.storage_[i] & mask)); + == (other.storage_[i] & mask)); } bool operator==(const bitvect& other) const { if (other.size_ != size_) - return false; + return false; if (size_ == 0) - return true; + return true; size_t i; size_t m = other.used_blocks(); const size_t bpb = 8 * sizeof(bitvect::block_t); size_t rest = size() % bpb; for (i = 0; i < m - !!rest; ++i) - if (storage_[i] != other.storage_[i]) - return false; + if (storage_[i] != other.storage_[i]) + return false; if (!rest) - return true; + return true; // The last block might not be fully used, compare only the // relevant portion. block_t mask = (1UL << rest) - 1; @@ -352,18 +352,18 @@ namespace spot bool operator<(const bitvect& other) const { if (size_ != other.size_) - return size_ < other.size_; + return size_ < other.size_; if (size_ == 0) - return false; + return false; size_t i; size_t m = other.used_blocks(); const size_t bpb = 8 * sizeof(bitvect::block_t); size_t rest = size() % bpb; for (i = 0; i < m - !!rest; ++i) - if (storage_[i] > other.storage_[i]) - return false; + if (storage_[i] > other.storage_[i]) + return false; if (!rest) - return true; + return true; // The last block might not be fully used, compare only the // relevant portion. block_t mask = (1UL << rest) - 1; @@ -398,7 +398,7 @@ namespace spot res->make_empty(); if (end == begin) - return res; + return res; const size_t bpb = 8 * sizeof(bitvect::block_t); @@ -407,32 +407,32 @@ namespace spot size_t indexe = (end - 1) / bpb; if (indexb == indexe) - { - block_t data = storage_[indexb]; - data >>= bitb; - res->push_back(data, count); - } + { + block_t data = storage_[indexb]; + data >>= bitb; + res->push_back(data, count); + } else - { - block_t data = storage_[indexb]; - data >>= bitb; - res->push_back(data, bpb - bitb); - count -= bpb - bitb; - while (count >= bpb) - { - ++indexb; - res->push_back(storage_[indexb], bpb); - count -= bpb; - assert(indexb != indexe || count == 0); - } - if (count > 0) - { - ++indexb; - assert(indexb == indexe); - assert(count == end % bpb); - res->push_back(storage_[indexb], count); - } - } + { + block_t data = storage_[indexb]; + data >>= bitb; + res->push_back(data, bpb - bitb); + count -= bpb - bitb; + while (count >= bpb) + { + ++indexb; + res->push_back(storage_[indexb], bpb); + count -= bpb; + assert(indexb != indexe || count == 0); + } + if (count > 0) + { + ++indexb; + assert(indexb == indexe); + assert(count == end % bpb); + res->push_back(storage_[indexb], count); + } + } return res; } @@ -441,12 +441,12 @@ namespace spot /// Print a bitvect. friend SPOT_API std::ostream& operator<<(std::ostream&, - const bitvect&); + const bitvect&); private: friend SPOT_API bitvect_array* ::spot::make_bitvect_array(size_t bitcount, - size_t vectcount); + size_t vectcount); size_t size_; size_t block_count_; @@ -485,7 +485,7 @@ namespace spot ~bitvect_array() { for (size_t i = 0; i < size_; ++i) - at(i).~bitvect(); + at(i).~bitvect(); } /// The number of bitvect in the array. @@ -506,7 +506,7 @@ namespace spot // FIXME: This could be changed into a large memset if the // individual vectors where not allowed to be reallocated. for (unsigned s = 0; s < size_; s++) - at(s).clear_all(); + at(s).clear_all(); } /// Return the bit-vector at \a index. @@ -518,12 +518,12 @@ namespace spot friend SPOT_API bitvect_array* ::spot::make_bitvect_array(size_t bitcount, - size_t vectcount); + size_t vectcount); /// Print a bitvect_array. friend SPOT_API std::ostream& operator<<(std::ostream&, - const bitvect_array&); + const bitvect_array&); private: size_t size_; diff --git a/spot/misc/common.hh b/spot/misc/common.hh index 5a367ae02..369ecdea4 100644 --- a/spot/misc/common.hh +++ b/spot/misc/common.hh @@ -93,9 +93,9 @@ // The extra parentheses in assert() is so that this // pattern is not caught by the style checker. -#define SPOT_UNREACHABLE() do { \ - assert(!("unreachable code reached")); \ - SPOT_UNREACHABLE_BUILTIN(); \ +#define SPOT_UNREACHABLE() do { \ + assert(!("unreachable code reached")); \ + SPOT_UNREACHABLE_BUILTIN(); \ } while (0) #define SPOT_UNIMPLEMENTED() throw std::runtime_error("unimplemented"); diff --git a/spot/misc/escape.cc b/spot/misc/escape.cc index 7024d090f..b9035a185 100644 --- a/spot/misc/escape.cc +++ b/spot/misc/escape.cc @@ -33,14 +33,14 @@ namespace spot { for (auto i: str) switch (i) - { - case '"': - os << "\"\""; - break; - default: - os << i; - break; - } + { + case '"': + os << "\"\""; + break; + default: + os << i; + break; + } return os; } @@ -49,28 +49,28 @@ namespace spot { for (auto i: str) switch (i) - { - case '~': - os << "\\text{\\textasciitilde}"; - break; - case '^': - os << "\\text{\\textasciicircum}"; - break; - case '\\': - os << "\\text{\\textbackslash}"; - break; - case '&': - case '%': - case '$': - case '#': - case '_': - case '{': - case '}': - os << '\\'; - default: - os << i; - break; - } + { + case '~': + os << "\\text{\\textasciitilde}"; + break; + case '^': + os << "\\text{\\textasciicircum}"; + break; + case '\\': + os << "\\text{\\textbackslash}"; + break; + case '&': + case '%': + case '$': + case '#': + case '_': + case '{': + case '}': + os << '\\'; + default: + os << i; + break; + } return os; } @@ -79,23 +79,23 @@ namespace spot { for (auto i: str) switch (i) - { - case '&': - os << "&"; - break; - case '"': - os << """; - break; - case '<': - os << "<"; - break; - case '>': - os << ">"; - break; - default: - os << i; - break; - } + { + case '&': + os << "&"; + break; + case '"': + os << """; + break; + case '<': + os << "<"; + break; + case '>': + os << ">"; + break; + default: + os << i; + break; + } return os; } @@ -104,20 +104,20 @@ namespace spot { for (auto i: str) switch (i) - { - case '\\': - os << "\\\\"; - break; - case '"': - os << "\\\""; - break; - case '\n': - os << "\\n"; - break; - default: - os << i; - break; - } + { + case '\\': + os << "\\\\"; + break; + case '"': + os << "\\\""; + break; + case '\n': + os << "\\n"; + break; + default: + os << i; + break; + } return os; } @@ -135,26 +135,26 @@ namespace spot // Single quotes are best, unless the string to quote contains one. if (!strchr(str, '\'')) { - os << '\'' << str << '\''; + os << '\'' << str << '\''; } else { - // In double quotes we have to escape $ ` " or \. - os << '"'; - while (*str) - switch (*str) - { - case '$': - case '`': - case '"': - case '\\': - os << '\\'; - // fall through - default: - os << *str++; - break; - } - os << '"'; + // In double quotes we have to escape $ ` " or \. + os << '"'; + while (*str) + switch (*str) + { + case '$': + case '`': + case '"': + case '\\': + os << '\\'; + // fall through + default: + os << *str++; + break; + } + os << '"'; } return os; } diff --git a/spot/misc/fixpool.hh b/spot/misc/fixpool.hh index df60f48fd..9c1fbd288 100644 --- a/spot/misc/fixpool.hh +++ b/spot/misc/fixpool.hh @@ -34,22 +34,22 @@ namespace spot /// Create a pool allocating objects of \a size bytes. fixed_size_pool(size_t size) : freelist_(nullptr), free_start_(nullptr), - free_end_(nullptr), chunklist_(nullptr) + free_end_(nullptr), chunklist_(nullptr) { const size_t alignement = 2 * sizeof(size_t); size_ = ((size >= sizeof(block_) ? size : sizeof(block_)) - + alignement - 1) & ~(alignement - 1); + + alignement - 1) & ~(alignement - 1); } /// Free any memory allocated by this pool. ~fixed_size_pool() { while (chunklist_) - { - chunk_* prev = chunklist_->prev; - free(chunklist_); - chunklist_ = prev; - } + { + chunk_* prev = chunklist_->prev; + free(chunklist_); + chunklist_ = prev; + } } /// Allocate \a size bytes of memory. @@ -59,27 +59,27 @@ namespace spot block_* f = freelist_; // If we have free blocks available, return the first one. if (f) - { - freelist_ = f->next; - return f; - } + { + freelist_ = f->next; + return f; + } // Else, create a block out of the last chunk of allocated // memory. // If all the last chunk has been used, allocate one more. if (free_start_ + size_ > free_end_) - { - const size_t requested = (size_ > 128 ? size_ : 128) * 8192 - 64; - chunk_* c = reinterpret_cast(malloc(requested)); - if (!c) - throw std::bad_alloc(); - c->prev = chunklist_; - chunklist_ = c; + { + const size_t requested = (size_ > 128 ? size_ : 128) * 8192 - 64; + chunk_* c = reinterpret_cast(malloc(requested)); + if (!c) + throw std::bad_alloc(); + c->prev = chunklist_; + chunklist_ = c; - free_start_ = c->data_ + size_; - free_end_ = c->data_ + requested; - } + free_start_ = c->data_ + size_; + free_end_ = c->data_ + requested; + } void* res = free_start_; free_start_ += size_; diff --git a/spot/misc/formater.cc b/spot/misc/formater.cc index 8d771363c..a2a817ae9 100644 --- a/spot/misc/formater.cc +++ b/spot/misc/formater.cc @@ -28,12 +28,12 @@ namespace spot { for (const char* pos = fmt; *pos; ++pos) if (*pos == '%') - { - char c = *++pos; - has[c] = true; - if (!c) - break; - } + { + char c = *++pos; + has[c] = true; + if (!c) + break; + } } void @@ -46,17 +46,17 @@ namespace spot formater::format(const char* fmt) { for (const char* pos = fmt; *pos; ++pos) - if (*pos != '%') - { - *output_ << *pos; - } - else - { - char c = *++pos; - call_[c]->print(*output_, pos); - if (!c) - break; - } + if (*pos != '%') + { + *output_ << *pos; + } + else + { + char c = *++pos; + call_[c]->print(*output_, pos); + if (!c) + break; + } return *output_; } } diff --git a/spot/misc/hash.hh b/spot/misc/hash.hh index a45288e33..33dd3f233 100644 --- a/spot/misc/hash.hh +++ b/spot/misc/hash.hh @@ -49,7 +49,7 @@ namespace spot size_t operator()(const T* p) const { return knuth32_hash(reinterpret_cast(p) - - static_cast(nullptr)); + - static_cast(nullptr)); } }; @@ -85,7 +85,7 @@ namespace spot std::hash uh; return wang32_hash(static_cast(th(p.first)) ^ - static_cast(uh(p.second))); + static_cast(uh(p.second))); } }; } diff --git a/spot/misc/intvcmp2.cc b/spot/misc/intvcmp2.cc index 3f029f64b..204b74867 100644 --- a/spot/misc/intvcmp2.cc +++ b/spot/misc/intvcmp2.cc @@ -43,270 +43,270 @@ namespace spot { public: stream_compression_base(size_t size) - : size_(size) + : size_(size) { } void run() { - static const unsigned bits_width[7] = { 1, 3, 5, 7, 9, 14, 28 }; - static const unsigned max_count[8] = { 30, 10, 6, 4, 3, 2, 1, 0 }; - static const unsigned max_allowed[8] = { 1, - (1 << 3) - 1, - (1 << 5) - 1, - (1 << 7) - 1, - (1 << 9) - 1, - (1 << 14) - 1, - (1 << 28) - 1, - -1U }; - // If we have only X data to compress and they fit with the - // current bit width, the following table tells us we should - // use bits_width[count_to_level[X - 1]] to limit the number - // of trailing zeros we encode. E.g. count_to_level[5 - 1] - // is 2, which mean that 5 values should be encoded with - // bits_width[2] == 5 bits. - static const unsigned count_to_level[30] = - { - 6, // 1 - 5, // 2 - 4, // 3 - 3, // 4 - 2, // 5 - 2, // 6 - 1, // 7 - 1, // 8 - 1, // 9 - 1, // 10 - 0, 0, 0, 0, 0, // 11-15 - 0, 0, 0, 0, 0, // 16-20 - 0, 0, 0, 0, 0, // 21-25 - 0, 0, 0, 0, 0, // 26-30 - }; + static const unsigned bits_width[7] = { 1, 3, 5, 7, 9, 14, 28 }; + static const unsigned max_count[8] = { 30, 10, 6, 4, 3, 2, 1, 0 }; + static const unsigned max_allowed[8] = { 1, + (1 << 3) - 1, + (1 << 5) - 1, + (1 << 7) - 1, + (1 << 9) - 1, + (1 << 14) - 1, + (1 << 28) - 1, + -1U }; + // If we have only X data to compress and they fit with the + // current bit width, the following table tells us we should + // use bits_width[count_to_level[X - 1]] to limit the number + // of trailing zeros we encode. E.g. count_to_level[5 - 1] + // is 2, which mean that 5 values should be encoded with + // bits_width[2] == 5 bits. + static const unsigned count_to_level[30] = + { + 6, // 1 + 5, // 2 + 4, // 3 + 3, // 4 + 2, // 5 + 2, // 6 + 1, // 7 + 1, // 8 + 1, // 9 + 1, // 10 + 0, 0, 0, 0, 0, // 11-15 + 0, 0, 0, 0, 0, // 16-20 + 0, 0, 0, 0, 0, // 21-25 + 0, 0, 0, 0, 0, // 26-30 + }; - while (size_ > 0) - { - unsigned id = 0; // Current level in the above two tables. - unsigned curmax_allowed = max_allowed[id]; - unsigned compressable = 0; // Number of integers ready to pack. - do - { - unsigned int val = self().data_at(compressable); - ++compressable; - while (val > curmax_allowed) - { - curmax_allowed = max_allowed[++id]; + while (size_ > 0) + { + unsigned id = 0; // Current level in the above two tables. + unsigned curmax_allowed = max_allowed[id]; + unsigned compressable = 0; // Number of integers ready to pack. + do + { + unsigned int val = self().data_at(compressable); + ++compressable; + while (val > curmax_allowed) + { + curmax_allowed = max_allowed[++id]; - if (compressable > max_count[id]) - goto fast_encode; - } - if (compressable >= max_count[id]) - goto fast_encode; - } - while (SPOT_LIKELY(compressable < size_)); + if (compressable > max_count[id]) + goto fast_encode; + } + if (compressable >= max_count[id]) + goto fast_encode; + } + while (SPOT_LIKELY(compressable < size_)); - assert(compressable < max_count[id]); + assert(compressable < max_count[id]); - // Since we have less data than the current "id" allows, - // try to use more bits so we can encode faster. + // Since we have less data than the current "id" allows, + // try to use more bits so we can encode faster. - id = count_to_level[compressable - 1]; + id = count_to_level[compressable - 1]; - if (compressable == max_count[id]) - goto fast_encode; + if (compressable == max_count[id]) + goto fast_encode; - // Slow compression for situations where we have - // compressable < max_count[id]. We can only be in - // one of the 3 first "id" (1, 3, or 5 bits); - { - assert(id <= 2); - unsigned bits = bits_width[id]; - unsigned finalshifts = (max_count[id] - compressable) * bits; - size_t pos = 0; - unsigned output = self().data_at(pos); - while (--compressable) - { - output <<= bits; - output += self().data_at(++pos); - } - output <<= finalshifts; - output += id << 30; - self().push_data(output); - return; - } + // Slow compression for situations where we have + // compressable < max_count[id]. We can only be in + // one of the 3 first "id" (1, 3, or 5 bits); + { + assert(id <= 2); + unsigned bits = bits_width[id]; + unsigned finalshifts = (max_count[id] - compressable) * bits; + size_t pos = 0; + unsigned output = self().data_at(pos); + while (--compressable) + { + output <<= bits; + output += self().data_at(++pos); + } + output <<= finalshifts; + output += id << 30; + self().push_data(output); + return; + } - fast_encode: - switch (id) - { - case 0: // 30 1-bit values - { - // This code has been tuned so that the compiler can - // efficiently encode it as a series of MOV+LEA - // instructions, without shifts. For instance - // - // output <<= 1; - // output += self().data_at(4); - // - // translates to (assuming %eax points to the input, - // and %edx holds the output) the following: - // - // mov ecx, [eax+16] - // lea edx, [ecx+edx*2] - // - // This optimization is the reason why we use 'output +=' - // instead of the more intuitive 'output |=' everywhere in - // this file. + fast_encode: + switch (id) + { + case 0: // 30 1-bit values + { + // This code has been tuned so that the compiler can + // efficiently encode it as a series of MOV+LEA + // instructions, without shifts. For instance + // + // output <<= 1; + // output += self().data_at(4); + // + // translates to (assuming %eax points to the input, + // and %edx holds the output) the following: + // + // mov ecx, [eax+16] + // lea edx, [ecx+edx*2] + // + // This optimization is the reason why we use 'output +=' + // instead of the more intuitive 'output |=' everywhere in + // this file. - unsigned int output = 0x00 << 1; // 00 - output += self().data_at(0); - output <<= 1; - output += self().data_at(1); - output <<= 1; - output += self().data_at(2); - output <<= 1; - output += self().data_at(3); - output <<= 1; - output += self().data_at(4); - output <<= 1; - output += self().data_at(5); - output <<= 1; - output += self().data_at(6); - output <<= 1; - output += self().data_at(7); - output <<= 1; - output += self().data_at(8); - output <<= 1; - output += self().data_at(9); - output <<= 1; - output += self().data_at(10); - output <<= 1; - output += self().data_at(11); - output <<= 1; - output += self().data_at(12); - output <<= 1; - output += self().data_at(13); - output <<= 1; - output += self().data_at(14); - output <<= 1; - output += self().data_at(15); - output <<= 1; - output += self().data_at(16); - output <<= 1; - output += self().data_at(17); - output <<= 1; - output += self().data_at(18); - output <<= 1; - output += self().data_at(19); - output <<= 1; - output += self().data_at(20); - output <<= 1; - output += self().data_at(21); - output <<= 1; - output += self().data_at(22); - output <<= 1; - output += self().data_at(23); - output <<= 1; - output += self().data_at(24); - output <<= 1; - output += self().data_at(25); - output <<= 1; - output += self().data_at(26); - output <<= 1; - output += self().data_at(27); - output <<= 1; - output += self().data_at(28); - output <<= 1; - output += self().data_at(29); - self().push_data(output); - } - break; - case 1: // 10 3-bit values - { - // This code has been tuned so that the compiler can - // efficiently encode it as a series of MOV+LEA - // instructions, without shifts. For instance - // - // output <<= 3; - // output += self().data_at(4); - // - // translates to (assuming %eax points to the input, - // and %edx holds the output) the following: - // - // mov ecx, [eax+16] - // lea edx, [ecx+edx*8] + unsigned int output = 0x00 << 1; // 00 + output += self().data_at(0); + output <<= 1; + output += self().data_at(1); + output <<= 1; + output += self().data_at(2); + output <<= 1; + output += self().data_at(3); + output <<= 1; + output += self().data_at(4); + output <<= 1; + output += self().data_at(5); + output <<= 1; + output += self().data_at(6); + output <<= 1; + output += self().data_at(7); + output <<= 1; + output += self().data_at(8); + output <<= 1; + output += self().data_at(9); + output <<= 1; + output += self().data_at(10); + output <<= 1; + output += self().data_at(11); + output <<= 1; + output += self().data_at(12); + output <<= 1; + output += self().data_at(13); + output <<= 1; + output += self().data_at(14); + output <<= 1; + output += self().data_at(15); + output <<= 1; + output += self().data_at(16); + output <<= 1; + output += self().data_at(17); + output <<= 1; + output += self().data_at(18); + output <<= 1; + output += self().data_at(19); + output <<= 1; + output += self().data_at(20); + output <<= 1; + output += self().data_at(21); + output <<= 1; + output += self().data_at(22); + output <<= 1; + output += self().data_at(23); + output <<= 1; + output += self().data_at(24); + output <<= 1; + output += self().data_at(25); + output <<= 1; + output += self().data_at(26); + output <<= 1; + output += self().data_at(27); + output <<= 1; + output += self().data_at(28); + output <<= 1; + output += self().data_at(29); + self().push_data(output); + } + break; + case 1: // 10 3-bit values + { + // This code has been tuned so that the compiler can + // efficiently encode it as a series of MOV+LEA + // instructions, without shifts. For instance + // + // output <<= 3; + // output += self().data_at(4); + // + // translates to (assuming %eax points to the input, + // and %edx holds the output) the following: + // + // mov ecx, [eax+16] + // lea edx, [ecx+edx*8] - unsigned int output = 0x01 << 3; // 01 - output += self().data_at(0); - output <<= 3; - output += self().data_at(1); - output <<= 3; - output += self().data_at(2); - output <<= 3; - output += self().data_at(3); - output <<= 3; - output += self().data_at(4); - output <<= 3; - output += self().data_at(5); - output <<= 3; - output += self().data_at(6); - output <<= 3; - output += self().data_at(7); - output <<= 3; - output += self().data_at(8); - output <<= 3; - output += self().data_at(9); - self().push_data(output); - } - break; - case 2: // 6 5-bit values - { - unsigned int output = 0x02U << 30; // 10 - output += self().data_at(0) << 25; - output += self().data_at(1) << 20; - output += self().data_at(2) << 15; - output += self().data_at(3) << 10; - output += self().data_at(4) << 5; - output += self().data_at(5); - self().push_data(output); - } - break; - case 3: // 4 7-bit values - { - unsigned int output = 0x0CU << 28; // 1100 - output += self().data_at(0) << 21; - output += self().data_at(1) << 14; - output += self().data_at(2) << 7; - output += self().data_at(3); - self().push_data(output); - } - break; - case 4: // 3 9-bit values - { - unsigned int output = 0x0DU << 28; // 1101x (1 bit lost) - output += self().data_at(0) << 18; - output += self().data_at(1) << 9; - output += self().data_at(2); - self().push_data(output); - } - break; - case 5: // 2 14-bit values - { - unsigned int output = 0x0EU << 28; // 1110 - output += self().data_at(0) << 14; - output += self().data_at(1); - self().push_data(output); - } - break; - case 6: // one 28-bit value - { - unsigned int output = 0x0FU << 28; // 1111 - output += self().data_at(0); - self().push_data(output); - } - break; - } - self().forward(max_count[id]); - size_ -= max_count[id]; - } + unsigned int output = 0x01 << 3; // 01 + output += self().data_at(0); + output <<= 3; + output += self().data_at(1); + output <<= 3; + output += self().data_at(2); + output <<= 3; + output += self().data_at(3); + output <<= 3; + output += self().data_at(4); + output <<= 3; + output += self().data_at(5); + output <<= 3; + output += self().data_at(6); + output <<= 3; + output += self().data_at(7); + output <<= 3; + output += self().data_at(8); + output <<= 3; + output += self().data_at(9); + self().push_data(output); + } + break; + case 2: // 6 5-bit values + { + unsigned int output = 0x02U << 30; // 10 + output += self().data_at(0) << 25; + output += self().data_at(1) << 20; + output += self().data_at(2) << 15; + output += self().data_at(3) << 10; + output += self().data_at(4) << 5; + output += self().data_at(5); + self().push_data(output); + } + break; + case 3: // 4 7-bit values + { + unsigned int output = 0x0CU << 28; // 1100 + output += self().data_at(0) << 21; + output += self().data_at(1) << 14; + output += self().data_at(2) << 7; + output += self().data_at(3); + self().push_data(output); + } + break; + case 4: // 3 9-bit values + { + unsigned int output = 0x0DU << 28; // 1101x (1 bit lost) + output += self().data_at(0) << 18; + output += self().data_at(1) << 9; + output += self().data_at(2); + self().push_data(output); + } + break; + case 5: // 2 14-bit values + { + unsigned int output = 0x0EU << 28; // 1110 + output += self().data_at(0) << 14; + output += self().data_at(1); + self().push_data(output); + } + break; + case 6: // one 28-bit value + { + unsigned int output = 0x0FU << 28; // 1111 + output += self().data_at(0); + self().push_data(output); + } + break; + } + self().forward(max_count[id]); + size_ -= max_count[id]; + } } protected: @@ -315,12 +315,12 @@ namespace spot Self& self() { - return static_cast(*this); + return static_cast(*this); } const Self& self() const { - return static_cast(*this); + return static_cast(*this); } }; @@ -331,29 +331,29 @@ namespace spot { public: int_array_array_compression(const int* array, size_t n, - int* dest, size_t& dest_n) - : stream_compression_base(n), - array_(array), result_size_(dest_n), - result_(dest), result_end_(dest + dest_n) + int* dest, size_t& dest_n) + : stream_compression_base(n), + array_(array), result_size_(dest_n), + result_(dest), result_end_(dest + dest_n) { - result_size_ = 0; // this resets dest_n. + result_size_ = 0; // this resets dest_n. } void push_data(unsigned int i) { - assert(result_ < result_end_); - ++result_size_; - *result_++ = static_cast(i); + assert(result_ < result_end_); + ++result_size_; + *result_++ = static_cast(i); } unsigned int data_at(size_t offset) { - return static_cast(array_[offset]); + return static_cast(array_[offset]); } void forward(size_t offset) { - array_ += offset; + array_ += offset; } protected: @@ -368,7 +368,7 @@ namespace spot void int_array_array_compress2(const int* array, size_t n, - int* dest, size_t& dest_size) + int* dest, size_t& dest_size) { int_array_array_compression c(array, n, dest, dest_size); c.run(); @@ -386,113 +386,113 @@ namespace spot void run() { - while (SPOT_LIKELY(self().have_comp_data())) - { - unsigned val = self().next_comp_data(); + while (SPOT_LIKELY(self().have_comp_data())) + { + unsigned val = self().next_comp_data(); - unsigned id = val >> 28; - switch (id) - { - case 0x00: // 00xx - 30 1-bit values. - case 0x01: - case 0x02: - case 0x03: - self().write_data_at(0, !!(val & (1 << 29))); - self().write_data_at(1, !!(val & (1 << 28))); - self().write_data_at(2, !!(val & (1 << 27))); - self().write_data_at(3, !!(val & (1 << 26))); - self().write_data_at(4, !!(val & (1 << 25))); - self().write_data_at(5, !!(val & (1 << 24))); - self().write_data_at(6, !!(val & (1 << 23))); - self().write_data_at(7, !!(val & (1 << 22))); - self().write_data_at(8, !!(val & (1 << 21))); - self().write_data_at(9, !!(val & (1 << 20))); - self().write_data_at(10, !!(val & (1 << 19))); - self().write_data_at(11, !!(val & (1 << 18))); - self().write_data_at(12, !!(val & (1 << 17))); - self().write_data_at(13, !!(val & (1 << 16))); - self().write_data_at(14, !!(val & (1 << 15))); - self().write_data_at(15, !!(val & (1 << 14))); - self().write_data_at(16, !!(val & (1 << 13))); - self().write_data_at(17, !!(val & (1 << 12))); - self().write_data_at(18, !!(val & (1 << 11))); - self().write_data_at(19, !!(val & (1 << 10))); - self().write_data_at(20, !!(val & (1 << 9))); - self().write_data_at(21, !!(val & (1 << 8))); - self().write_data_at(22, !!(val & (1 << 7))); - self().write_data_at(23, !!(val & (1 << 6))); - self().write_data_at(24, !!(val & (1 << 5))); - self().write_data_at(25, !!(val & (1 << 4))); - self().write_data_at(26, !!(val & (1 << 3))); - self().write_data_at(27, !!(val & (1 << 2))); - self().write_data_at(28, !!(val & (1 << 1))); - self().write_data_at(29, !!(val & (1 << 0))); - self().forward(30); - break; - case 0x04: // 01xx - 10 3-bit values. - case 0x05: - case 0x06: - case 0x07: - self().write_data_at(0, (val >> 27) & 0x07); - self().write_data_at(1, (val >> 24) & 0x07); - self().write_data_at(2, (val >> 21) & 0x07); - self().write_data_at(3, (val >> 18) & 0x07); - self().write_data_at(4, (val >> 15) & 0x07); - self().write_data_at(5, (val >> 12) & 0x07); - self().write_data_at(6, (val >> 9) & 0x07); - self().write_data_at(7, (val >> 6) & 0x07); - self().write_data_at(8, (val >> 3) & 0x07); - self().write_data_at(9, (val >> 0) & 0x07); - self().forward(10); - break; - case 0x08: // 10xx - 6 5-bit values. - case 0x09: - case 0x0A: - case 0x0B: - self().write_data_at(0, (val >> 25) & 0x1F); - self().write_data_at(1, (val >> 20) & 0x1F); - self().write_data_at(2, (val >> 15) & 0x1F); - self().write_data_at(3, (val >> 10) & 0x1F); - self().write_data_at(4, (val >> 5) & 0x1F); - self().write_data_at(5, (val >> 0) & 0x1F); - self().forward(6); - break; - case 0x0C: // 1100 - 4 7-bit values - self().write_data_at(0, (val >> 21) & 0x7F); - self().write_data_at(1, (val >> 14) & 0x7F); - self().write_data_at(2, (val >> 7) & 0x7F); - self().write_data_at(3, (val >> 0) & 0x7F); - self().forward(4); - break; - case 0x0D: // 1101x - 3 9-bit values. - self().write_data_at(0, (val >> 18) & 0x1FF); - self().write_data_at(1, (val >> 9) & 0x1FF); - self().write_data_at(2, (val >> 0) & 0x1FF); - self().forward(3); - break; - case 0x0E: // 110x - 2 14-bit values. - self().write_data_at(0, (val >> 14) & 0x3FFF); - self().write_data_at(1, (val >> 0) & 0x3FFF); - self().forward(2); - break; - case 0x0F: // 1100 - 1 28-bit value. - self().write_data_at(0, val & 0xFFFFFFF); - self().forward(1); - break; - } - } + unsigned id = val >> 28; + switch (id) + { + case 0x00: // 00xx - 30 1-bit values. + case 0x01: + case 0x02: + case 0x03: + self().write_data_at(0, !!(val & (1 << 29))); + self().write_data_at(1, !!(val & (1 << 28))); + self().write_data_at(2, !!(val & (1 << 27))); + self().write_data_at(3, !!(val & (1 << 26))); + self().write_data_at(4, !!(val & (1 << 25))); + self().write_data_at(5, !!(val & (1 << 24))); + self().write_data_at(6, !!(val & (1 << 23))); + self().write_data_at(7, !!(val & (1 << 22))); + self().write_data_at(8, !!(val & (1 << 21))); + self().write_data_at(9, !!(val & (1 << 20))); + self().write_data_at(10, !!(val & (1 << 19))); + self().write_data_at(11, !!(val & (1 << 18))); + self().write_data_at(12, !!(val & (1 << 17))); + self().write_data_at(13, !!(val & (1 << 16))); + self().write_data_at(14, !!(val & (1 << 15))); + self().write_data_at(15, !!(val & (1 << 14))); + self().write_data_at(16, !!(val & (1 << 13))); + self().write_data_at(17, !!(val & (1 << 12))); + self().write_data_at(18, !!(val & (1 << 11))); + self().write_data_at(19, !!(val & (1 << 10))); + self().write_data_at(20, !!(val & (1 << 9))); + self().write_data_at(21, !!(val & (1 << 8))); + self().write_data_at(22, !!(val & (1 << 7))); + self().write_data_at(23, !!(val & (1 << 6))); + self().write_data_at(24, !!(val & (1 << 5))); + self().write_data_at(25, !!(val & (1 << 4))); + self().write_data_at(26, !!(val & (1 << 3))); + self().write_data_at(27, !!(val & (1 << 2))); + self().write_data_at(28, !!(val & (1 << 1))); + self().write_data_at(29, !!(val & (1 << 0))); + self().forward(30); + break; + case 0x04: // 01xx - 10 3-bit values. + case 0x05: + case 0x06: + case 0x07: + self().write_data_at(0, (val >> 27) & 0x07); + self().write_data_at(1, (val >> 24) & 0x07); + self().write_data_at(2, (val >> 21) & 0x07); + self().write_data_at(3, (val >> 18) & 0x07); + self().write_data_at(4, (val >> 15) & 0x07); + self().write_data_at(5, (val >> 12) & 0x07); + self().write_data_at(6, (val >> 9) & 0x07); + self().write_data_at(7, (val >> 6) & 0x07); + self().write_data_at(8, (val >> 3) & 0x07); + self().write_data_at(9, (val >> 0) & 0x07); + self().forward(10); + break; + case 0x08: // 10xx - 6 5-bit values. + case 0x09: + case 0x0A: + case 0x0B: + self().write_data_at(0, (val >> 25) & 0x1F); + self().write_data_at(1, (val >> 20) & 0x1F); + self().write_data_at(2, (val >> 15) & 0x1F); + self().write_data_at(3, (val >> 10) & 0x1F); + self().write_data_at(4, (val >> 5) & 0x1F); + self().write_data_at(5, (val >> 0) & 0x1F); + self().forward(6); + break; + case 0x0C: // 1100 - 4 7-bit values + self().write_data_at(0, (val >> 21) & 0x7F); + self().write_data_at(1, (val >> 14) & 0x7F); + self().write_data_at(2, (val >> 7) & 0x7F); + self().write_data_at(3, (val >> 0) & 0x7F); + self().forward(4); + break; + case 0x0D: // 1101x - 3 9-bit values. + self().write_data_at(0, (val >> 18) & 0x1FF); + self().write_data_at(1, (val >> 9) & 0x1FF); + self().write_data_at(2, (val >> 0) & 0x1FF); + self().forward(3); + break; + case 0x0E: // 110x - 2 14-bit values. + self().write_data_at(0, (val >> 14) & 0x3FFF); + self().write_data_at(1, (val >> 0) & 0x3FFF); + self().forward(2); + break; + case 0x0F: // 1100 - 1 28-bit value. + self().write_data_at(0, val & 0xFFFFFFF); + self().forward(1); + break; + } + } } protected: Self& self() { - return static_cast(*this); + return static_cast(*this); } const Self& self() const { - return static_cast(*this); + return static_cast(*this); } }; @@ -502,30 +502,30 @@ namespace spot { public: int_array_array_decompression(const int* array, - size_t array_size, - int* res) - : array_(array), n_(array_size), pos_(0), result_(res) + size_t array_size, + int* res) + : array_(array), n_(array_size), pos_(0), result_(res) { } void write_data_at(size_t pos, unsigned int i) { - result_[pos] = i; + result_[pos] = i; } void forward(size_t i) { - result_ += i; + result_ += i; } bool have_comp_data() const { - return pos_ < n_; + return pos_ < n_; } unsigned int next_comp_data() { - return array_[pos_++]; + return array_[pos_++]; } protected: @@ -540,7 +540,7 @@ namespace spot void int_array_array_decompress2(const int* array, size_t array_size, int* res, - size_t) + size_t) { int_array_array_decompression c(array, array_size, res); c.run(); diff --git a/spot/misc/intvcmp2.hh b/spot/misc/intvcmp2.hh index 2756e119d..95da48be6 100644 --- a/spot/misc/intvcmp2.hh +++ b/spot/misc/intvcmp2.hh @@ -36,7 +36,7 @@ namespace spot /// filled in \a dest SPOT_API void int_array_array_compress2(const int* array, size_t n, - int* dest, size_t& dest_size); + int* dest, size_t& dest_size); /// \brief Uncompress an int array of size \a array_size into a int /// array of size \a size. @@ -44,7 +44,7 @@ namespace spot /// \a size must be the exact expected size of uncompressed array. SPOT_API void int_array_array_decompress2(const int* array, size_t array_size, - int* res, size_t size); + int* res, size_t size); /// @} } diff --git a/spot/misc/intvcomp.cc b/spot/misc/intvcomp.cc index fbfd25035..abac2a0f8 100644 --- a/spot/misc/intvcomp.cc +++ b/spot/misc/intvcomp.cc @@ -55,129 +55,129 @@ namespace spot public: stream_compression_base() - : cur_(0), bits_left_(max_bits) + : cur_(0), bits_left_(max_bits) { } void emit(unsigned int val) { - if (val == 0) - { - self().push_bits(0x0, 2, 0x3); - } - else if (val == 1) - { - self().push_bits(0x2, 3, 0x7); - } - else if (val >= 2 && val <= 5) - { - self().push_bits(0x3, 3, 0x7); - self().push_bits(val - 2, 2, 0x3); - } - else if (val >= 6 && val <= 22) - { - self().push_bits(0x4, 3, 0x7); - self().push_bits(val - 6, 4, 0xf); - } - else - { - assert(val > 22); - self().push_bits(0x7, 3, 0x7); - self().push_bits(val, 32, -1U); - } + if (val == 0) + { + self().push_bits(0x0, 2, 0x3); + } + else if (val == 1) + { + self().push_bits(0x2, 3, 0x7); + } + else if (val >= 2 && val <= 5) + { + self().push_bits(0x3, 3, 0x7); + self().push_bits(val - 2, 2, 0x3); + } + else if (val >= 6 && val <= 22) + { + self().push_bits(0x4, 3, 0x7); + self().push_bits(val - 6, 4, 0xf); + } + else + { + assert(val > 22); + self().push_bits(0x7, 3, 0x7); + self().push_bits(val, 32, -1U); + } } void run() { - unsigned int last_val = 0; + unsigned int last_val = 0; - while (SPOT_LIKELY(self().have_data())) - { - unsigned int val = self().next_data(); - // Repeated value? Try to find more. - if (val == last_val) - { - unsigned int count = 1; - while (count < 40 && self().skip_if(val)) - ++count; + while (SPOT_LIKELY(self().have_data())) + { + unsigned int val = self().next_data(); + // Repeated value? Try to find more. + if (val == last_val) + { + unsigned int count = 1; + while (count < 40 && self().skip_if(val)) + ++count; - if ((val == 0 && count < 3) || (val == 1 && count == 1)) - { - // it is more efficient to emit 0 once or twice directly - // (e.g., 00 00 vs. 011 11) - // for value 1, repetition is worthwhile for count > 1 - // (e.g., 010 010 vs. 011 00) - while (count--) - emit(val); - } - else if (count < 9) - { - self().push_bits(0x5, 3, 0x7); - self().push_bits(count - 1, 3, 0x7); - } - else - { - self().push_bits(0x6, 3, 0x7); - self().push_bits(count - 9, 5, 0x1f); - } - } - else - { - emit(val); - last_val = val; - } - } - flush(); + if ((val == 0 && count < 3) || (val == 1 && count == 1)) + { + // it is more efficient to emit 0 once or twice directly + // (e.g., 00 00 vs. 011 11) + // for value 1, repetition is worthwhile for count > 1 + // (e.g., 010 010 vs. 011 00) + while (count--) + emit(val); + } + else if (count < 9) + { + self().push_bits(0x5, 3, 0x7); + self().push_bits(count - 1, 3, 0x7); + } + else + { + self().push_bits(0x6, 3, 0x7); + self().push_bits(count - 9, 5, 0x1f); + } + } + else + { + emit(val); + last_val = val; + } + } + flush(); } // This version assumes there is at least n bits free in cur_. void push_bits_unchecked(unsigned int bits, unsigned int n, unsigned int mask) { - cur_ <<= n; - cur_ |= (bits & mask); - if (SPOT_LIKELY(bits_left_ -= n)) - return; + cur_ <<= n; + cur_ |= (bits & mask); + if (SPOT_LIKELY(bits_left_ -= n)) + return; - self().push_data(cur_); - cur_ = 0; - bits_left_ = max_bits; + self().push_data(cur_); + cur_ = 0; + bits_left_ = max_bits; } void push_bits(unsigned int bits, unsigned int n, unsigned int mask) { - if (SPOT_LIKELY(n <= bits_left_)) - { - push_bits_unchecked(bits, n, mask); - return; - } + if (SPOT_LIKELY(n <= bits_left_)) + { + push_bits_unchecked(bits, n, mask); + return; + } - // bits_left_ < n + // bits_left_ < n - unsigned int right_bit_count = n - bits_left_; - unsigned int left = bits >> right_bit_count; - push_bits_unchecked(left, bits_left_, (1 << bits_left_) - 1); - push_bits_unchecked(bits, right_bit_count, (1 << right_bit_count) - 1); + unsigned int right_bit_count = n - bits_left_; + unsigned int left = bits >> right_bit_count; + push_bits_unchecked(left, bits_left_, (1 << bits_left_) - 1); + push_bits_unchecked(bits, right_bit_count, (1 << right_bit_count) - 1); } void flush() { - if (bits_left_ == max_bits) - return; - cur_ <<= bits_left_; - self().push_data(cur_); + if (bits_left_ == max_bits) + return; + cur_ <<= bits_left_; + self().push_data(cur_); } protected: Self& self() { - return static_cast(*this); + return static_cast(*this); } const Self& self() const { - return static_cast(*this); + return static_cast(*this); } unsigned int cur_; @@ -189,41 +189,41 @@ namespace spot { public: int_array_vector_compression(const int* array, size_t n) - : array_(array), n_(n), pos_(0), result_(new std::vector) + : array_(array), n_(n), pos_(0), result_(new std::vector) { } void push_data(unsigned int i) { - result_->push_back(i); + result_->push_back(i); } const std::vector* result() const { - return result_; + return result_; } bool have_data() const { - return pos_ < n_; + return pos_ < n_; } unsigned int next_data() { - return static_cast(array_[pos_++]); + return static_cast(array_[pos_++]); } bool skip_if(unsigned int val) { - if (SPOT_UNLIKELY(!have_data())) - return false; + if (SPOT_UNLIKELY(!have_data())) + return false; - if (static_cast(array_[pos_]) != val) - return false; + if (static_cast(array_[pos_]) != val) + return false; - ++pos_; - return true; + ++pos_; + return true; } protected: @@ -238,36 +238,36 @@ namespace spot { public: int_vector_vector_compression(const std::vector& input, - std::vector& output) - : input_(input), pos_(input.begin()), end_(input.end()), output_(output) + std::vector& output) + : input_(input), pos_(input.begin()), end_(input.end()), output_(output) { } void push_data(unsigned int i) { - output_.push_back(i); + output_.push_back(i); } bool have_data() const { - return pos_ < end_; + return pos_ < end_; } unsigned int next_data() { - return static_cast(*pos_++); + return static_cast(*pos_++); } bool skip_if(unsigned int val) { - if (SPOT_UNLIKELY(!have_data())) - return false; + if (SPOT_UNLIKELY(!have_data())) + return false; - if (static_cast(*pos_) != val) - return false; + if (static_cast(*pos_) != val) + return false; - ++pos_; - return true; + ++pos_; + return true; } protected: @@ -282,40 +282,40 @@ namespace spot { public: int_array_array_compression(const int* array, size_t n, - int* dest, size_t& dest_n) - : array_(array), n_(n), pos_(0), - result_size_(dest_n), result_(dest), result_end_(dest + dest_n) + int* dest, size_t& dest_n) + : array_(array), n_(n), pos_(0), + result_size_(dest_n), result_(dest), result_end_(dest + dest_n) { - result_size_ = 0; // this resets dest_n. + result_size_ = 0; // this resets dest_n. } void push_data(unsigned int i) { - assert(result_ < result_end_); - ++result_size_; - *result_++ = static_cast(i); + assert(result_ < result_end_); + ++result_size_; + *result_++ = static_cast(i); } bool have_data() const { - return pos_ < n_; + return pos_ < n_; } unsigned int next_data() { - return static_cast(array_[pos_++]); + return static_cast(array_[pos_++]); } bool skip_if(unsigned int val) { - if (SPOT_UNLIKELY(!have_data())) - return false; + if (SPOT_UNLIKELY(!have_data())) + return false; - if (static_cast(array_[pos_]) != val) - return false; + if (static_cast(array_[pos_]) != val) + return false; - ++pos_; - return true; + ++pos_; + return true; } protected: @@ -330,7 +330,7 @@ namespace spot void int_vector_vector_compress(const std::vector& input, - std::vector& output) + std::vector& output) { int_vector_vector_compression c(input, output); c.run(); @@ -346,7 +346,7 @@ namespace spot void int_array_array_compress(const int* array, size_t n, - int* dest, size_t& dest_size) + int* dest, size_t& dest_size) { int_array_array_compression c(array, n, dest, dest_size); c.run(); @@ -365,154 +365,154 @@ namespace spot public: void refill() { - if (SPOT_UNLIKELY(look_bits_ == 0)) - { - look_bits_ = max_bits; - look_ = buffer_; + if (SPOT_UNLIKELY(look_bits_ == 0)) + { + look_bits_ = max_bits; + look_ = buffer_; - if (SPOT_LIKELY(self().have_comp_data())) - buffer_ = self().next_comp_data(); + if (SPOT_LIKELY(self().have_comp_data())) + buffer_ = self().next_comp_data(); - if (SPOT_LIKELY(buffer_bits_ != max_bits)) - { - unsigned int fill_size = max_bits - buffer_bits_; - look_ <<= fill_size; - look_ |= buffer_ >> buffer_bits_; - } - } - else - { - unsigned int fill_size = max_bits - look_bits_; - if (fill_size > buffer_bits_) - fill_size = buffer_bits_; + if (SPOT_LIKELY(buffer_bits_ != max_bits)) + { + unsigned int fill_size = max_bits - buffer_bits_; + look_ <<= fill_size; + look_ |= buffer_ >> buffer_bits_; + } + } + else + { + unsigned int fill_size = max_bits - look_bits_; + if (fill_size > buffer_bits_) + fill_size = buffer_bits_; - look_ <<= fill_size; - buffer_bits_ -= fill_size; - look_ |= (buffer_ >> buffer_bits_) & ((1 << fill_size) - 1); - look_bits_ += fill_size; + look_ <<= fill_size; + buffer_bits_ -= fill_size; + look_ |= (buffer_ >> buffer_bits_) & ((1 << fill_size) - 1); + look_bits_ += fill_size; - if (buffer_bits_ == 0) - { - if (SPOT_LIKELY(self().have_comp_data())) - buffer_ = self().next_comp_data(); + if (buffer_bits_ == 0) + { + if (SPOT_LIKELY(self().have_comp_data())) + buffer_ = self().next_comp_data(); - unsigned int left = max_bits - look_bits_; - if (left != 0) - { - look_ <<= left; - look_ |= buffer_ >> look_bits_; - buffer_bits_ = look_bits_; - look_bits_ = max_bits; - } - else - { - buffer_bits_ = max_bits; - } - } - } + unsigned int left = max_bits - look_bits_; + if (left != 0) + { + look_ <<= left; + look_ |= buffer_ >> look_bits_; + buffer_bits_ = look_bits_; + look_bits_ = max_bits; + } + else + { + buffer_bits_ = max_bits; + } + } + } } unsigned int look_n_bits(unsigned int n) { - if (SPOT_UNLIKELY(look_bits_ < n)) - refill(); - assert(n <= look_bits_); - return (look_ >> (look_bits_ - n)) & ((1 << n) - 1); + if (SPOT_UNLIKELY(look_bits_ < n)) + refill(); + assert(n <= look_bits_); + return (look_ >> (look_bits_ - n)) & ((1 << n) - 1); } void skip_n_bits(unsigned int n) { - assert (n <= look_bits_); - look_bits_ -= n; + assert (n <= look_bits_); + look_bits_ -= n; } unsigned int get_n_bits(unsigned int n) { - if (SPOT_UNLIKELY(look_bits_ < n)) - refill(); - look_bits_ -= n; - return (look_ >> look_bits_) & ((1 << n) - 1); + if (SPOT_UNLIKELY(look_bits_ < n)) + refill(); + look_bits_ -= n; + return (look_ >> look_bits_) & ((1 << n) - 1); } unsigned int get_32_bits() { - // std::cerr << "get_32" << std::endl; - if (SPOT_LIKELY(look_bits_ < 32)) - refill(); - unsigned int val = look_; - look_bits_ = 0; - refill(); - return val; + // std::cerr << "get_32" << std::endl; + if (SPOT_LIKELY(look_bits_ < 32)) + refill(); + unsigned int val = look_; + look_bits_ = 0; + refill(); + return val; } void run() { - if (SPOT_UNLIKELY(!self().have_comp_data())) - return; + if (SPOT_UNLIKELY(!self().have_comp_data())) + return; - look_ = self().next_comp_data(); - look_bits_ = max_bits; - if (SPOT_LIKELY(self().have_comp_data())) - { - buffer_ = self().next_comp_data(); - buffer_bits_ = max_bits; - } - else - { - buffer_ = 0; - buffer_bits_ = 0; - } + look_ = self().next_comp_data(); + look_bits_ = max_bits; + if (SPOT_LIKELY(self().have_comp_data())) + { + buffer_ = self().next_comp_data(); + buffer_bits_ = max_bits; + } + else + { + buffer_ = 0; + buffer_bits_ = 0; + } - while (SPOT_LIKELY(!self().complete())) - { - unsigned int token = look_n_bits(3); - switch (token) - { - case 0x0: // 00[0] - case 0x1: // 00[1] - skip_n_bits(2); - self().push_data(0); - break; - case 0x2: // 010 - skip_n_bits(3); - self().push_data(1); - break; - case 0x3: // 011 - skip_n_bits(3); - self().push_data(2 + get_n_bits(2)); - break; - case 0x4: // 100 - skip_n_bits(3); - self().push_data(6 + get_n_bits(4)); - break; - case 0x5: // 101 - skip_n_bits(3); - self().repeat(1 + get_n_bits(3)); - break; - case 0x6: // 110 - skip_n_bits(3); - self().repeat(9 + get_n_bits(5)); - break; - case 0x7: // 111 - skip_n_bits(3); - self().push_data(get_32_bits()); - break; - default: - SPOT_UNREACHABLE(); - } - } + while (SPOT_LIKELY(!self().complete())) + { + unsigned int token = look_n_bits(3); + switch (token) + { + case 0x0: // 00[0] + case 0x1: // 00[1] + skip_n_bits(2); + self().push_data(0); + break; + case 0x2: // 010 + skip_n_bits(3); + self().push_data(1); + break; + case 0x3: // 011 + skip_n_bits(3); + self().push_data(2 + get_n_bits(2)); + break; + case 0x4: // 100 + skip_n_bits(3); + self().push_data(6 + get_n_bits(4)); + break; + case 0x5: // 101 + skip_n_bits(3); + self().repeat(1 + get_n_bits(3)); + break; + case 0x6: // 110 + skip_n_bits(3); + self().repeat(9 + get_n_bits(5)); + break; + case 0x7: // 111 + skip_n_bits(3); + self().push_data(get_32_bits()); + break; + default: + SPOT_UNREACHABLE(); + } + } } protected: Self& self() { - return static_cast(*this); + return static_cast(*this); } const Self& self() const { - return static_cast(*this); + return static_cast(*this); } unsigned int look_; @@ -526,41 +526,41 @@ namespace spot { public: int_vector_vector_decompression(const std::vector& array, - std::vector& res, size_t size) - : prev_(0), array_(array), - pos_(array.begin()), end_(array.end()), - result_(res), size_(size) + std::vector& res, size_t size) + : prev_(0), array_(array), + pos_(array.begin()), end_(array.end()), + result_(res), size_(size) { - result_.reserve(size); + result_.reserve(size); } bool complete() const { - return size_ == 0; + return size_ == 0; } void push_data(int i) { - prev_ = i; - result_.push_back(i); - --size_; + prev_ = i; + result_.push_back(i); + --size_; } void repeat(unsigned int i) { - size_ -= i; - while (i--) - result_.push_back(prev_); + size_ -= i; + while (i--) + result_.push_back(prev_); } bool have_comp_data() const { - return pos_ != end_; + return pos_ != end_; } unsigned int next_comp_data() { - return *pos_++; + return *pos_++; } protected: @@ -577,40 +577,40 @@ namespace spot { public: int_vector_array_decompression(const std::vector* array, - int* res, - size_t size) - : prev_(0), array_(array), n_(array->size()), pos_(0), result_(res), - size_(size) + int* res, + size_t size) + : prev_(0), array_(array), n_(array->size()), pos_(0), result_(res), + size_(size) { } bool complete() const { - return size_ == 0; + return size_ == 0; } void push_data(int i) { - prev_ = i; - *result_++ = i; - --size_; + prev_ = i; + *result_++ = i; + --size_; } void repeat(unsigned int i) { - size_ -= i; - while (i--) - *result_++ = prev_; + size_ -= i; + while (i--) + *result_++ = prev_; } bool have_comp_data() const { - return pos_ < n_; + return pos_ < n_; } unsigned int next_comp_data() { - return (*array_)[pos_++]; + return (*array_)[pos_++]; } protected: @@ -627,41 +627,41 @@ namespace spot { public: int_array_array_decompression(const int* array, - size_t array_size, - int* res, - size_t size) - : prev_(0), array_(array), n_(array_size), pos_(0), result_(res), - size_(size) + size_t array_size, + int* res, + size_t size) + : prev_(0), array_(array), n_(array_size), pos_(0), result_(res), + size_(size) { } bool complete() const { - return size_ == 0; + return size_ == 0; } void push_data(int i) { - prev_ = i; - *result_++ = i; - --size_; + prev_ = i; + *result_++ = i; + --size_; } void repeat(unsigned int i) { - size_ -= i; - while (i--) - *result_++ = prev_; + size_ -= i; + while (i--) + *result_++ = prev_; } bool have_comp_data() const { - return pos_ < n_; + return pos_ < n_; } unsigned int next_comp_data() { - return array_[pos_++]; + return array_[pos_++]; } protected: @@ -677,7 +677,7 @@ namespace spot void int_vector_vector_decompress(const std::vector& input, - std::vector& output, size_t size) + std::vector& output, size_t size) { int_vector_vector_decompression c(input, output, size); c.run(); @@ -685,7 +685,7 @@ namespace spot void int_vector_array_decompress(const std::vector* array, int* res, - size_t size) + size_t size) { int_vector_array_decompression c(array, res, size); c.run(); @@ -693,7 +693,7 @@ namespace spot void int_array_array_decompress(const int* array, size_t array_size, - int* res, size_t size) + int* res, size_t size) { int_array_array_decompression c(array, array_size, res, size); c.run(); diff --git a/spot/misc/intvcomp.hh b/spot/misc/intvcomp.hh index 235aa60d2..8bafc1527 100644 --- a/spot/misc/intvcomp.hh +++ b/spot/misc/intvcomp.hh @@ -31,7 +31,7 @@ namespace spot /// Compress an int vector into a vector of unsigned int. SPOT_API void int_vector_vector_compress(const std::vector& input, - std::vector& output); + std::vector& output); /// \brief Uncompress a vector of unsigned int into a vector of /// size \a size. @@ -39,7 +39,7 @@ namespace spot /// \a size must be the exact expected size of uncompressed array. SPOT_API void int_vector_vector_decompress(const std::vector& array, - std::vector& output, size_t size); + std::vector& output, size_t size); /// Compress an int array if size \a n into a vector of unsigned int. SPOT_API const std::vector* @@ -51,7 +51,7 @@ namespace spot /// \a size must be the exact expected size of uncompressed array. SPOT_API void int_vector_array_decompress(const std::vector* array, - int* res, size_t size); + int* res, size_t size); /// \brief Compress an int array of size \a n into a int array. /// @@ -61,7 +61,7 @@ namespace spot /// filled in \a dest SPOT_API void int_array_array_compress(const int* array, size_t n, - int* dest, size_t& dest_size); + int* dest, size_t& dest_size); /// \brief Uncompress an int array of size \a array_size into a int /// array of size \a size. @@ -69,7 +69,7 @@ namespace spot /// \a size must be the exact expected size of uncompressed array. SPOT_API void int_array_array_decompress(const int* array, size_t array_size, - int* res, size_t size); + int* res, size_t size); /// @} } diff --git a/spot/misc/location.hh b/spot/misc/location.hh index 67f00043c..f69185d71 100644 --- a/spot/misc/location.hh +++ b/spot/misc/location.hh @@ -157,8 +157,8 @@ namespace spot position last = loc.end - 1; ostr << loc.begin; if (last.filename - && (!loc.begin.filename - || *loc.begin.filename != *last.filename)) + && (!loc.begin.filename + || *loc.begin.filename != *last.filename)) ostr << '-' << last; else if (loc.begin.line != last.line) ostr << '-' << last.line << '.' << last.column; diff --git a/spot/misc/minato.cc b/spot/misc/minato.cc index 0eab66b19..596341d1c 100644 --- a/spot/misc/minato.cc +++ b/spot/misc/minato.cc @@ -51,12 +51,12 @@ namespace spot { if (input_min == input_max) { - cube_.push(bdd_satprefix(input_min)); - input_max = input_min; + cube_.push(bdd_satprefix(input_min)); + input_max = input_min; } else { - cube_.push(bddtrue); + cube_.push(bddtrue); } bdd common = input_min & input_max; todo_.emplace(input_min, input_max, bdd_support(common)); @@ -67,110 +67,110 @@ namespace spot { while (!todo_.empty()) { - local_vars& l = todo_.top(); - switch (l.step) - { - case local_vars::FirstStep: - next_var: - { - if (l.f_min == bddfalse) - { - ret_ = bddfalse; - todo_.pop(); - continue; - } - if (l.vars == bddtrue || l.f_max == bddtrue) - { - ret_ = l.f_max; - todo_.pop(); - return cube_.top() & ret_; - } - assert(l.vars != bddfalse); + local_vars& l = todo_.top(); + switch (l.step) + { + case local_vars::FirstStep: + next_var: + { + if (l.f_min == bddfalse) + { + ret_ = bddfalse; + todo_.pop(); + continue; + } + if (l.vars == bddtrue || l.f_max == bddtrue) + { + ret_ = l.f_max; + todo_.pop(); + return cube_.top() & ret_; + } + assert(l.vars != bddfalse); - // Pick the first variable in VARS that is used by F_MIN - // or F_MAX. We know that VARS, F_MIN or F_MAX are not - // constants (bddtrue or bddfalse) because one of the - // two above `if' would have matched; so it's ok to call - // bdd_var(). - int v = bdd_var(l.vars); - l.vars = bdd_high(l.vars); - int v_min = bdd_var(l.f_min); - int v_max = bdd_var(l.f_max); - if (v < v_min && v < v_max) - // Do not use a while() for this goto, because we want - // `continue' to be relative to the outermost while(). - goto next_var; + // Pick the first variable in VARS that is used by F_MIN + // or F_MAX. We know that VARS, F_MIN or F_MAX are not + // constants (bddtrue or bddfalse) because one of the + // two above `if' would have matched; so it's ok to call + // bdd_var(). + int v = bdd_var(l.vars); + l.vars = bdd_high(l.vars); + int v_min = bdd_var(l.f_min); + int v_max = bdd_var(l.f_max); + if (v < v_min && v < v_max) + // Do not use a while() for this goto, because we want + // `continue' to be relative to the outermost while(). + goto next_var; - l.step = local_vars::SecondStep; + l.step = local_vars::SecondStep; - bdd v0 = bdd_nithvar(v); - l.v1 = bdd_ithvar(v); + bdd v0 = bdd_nithvar(v); + l.v1 = bdd_ithvar(v); - // All the following should be equivalent to - // f0_min = bdd_restrict(f_min, v0); - // f0_max = bdd_restrict(f_max, v0); - // f1_min = bdd_restrict(f_min, v1); - // f1_max = bdd_restrict(f_max, v1); - // but we try to avoid bdd_restrict when possible. - if (v == v_min) - { - l.f0_min = bdd_low(l.f_min); - l.f1_min = bdd_high(l.f_min); - } - else if (v_min < v) - { - l.f0_min = bdd_restrict(l.f_min, v0); - l.f1_min = bdd_restrict(l.f_min, l.v1); - } - else - { - l.f1_min = l.f0_min = l.f_min; - } - if (v == v_max) - { - l.f0_max = bdd_low(l.f_max); - l.f1_max = bdd_high(l.f_max); - } - else if (v_max < v) - { - l.f0_max = bdd_restrict(l.f_max, v0); - l.f1_max = bdd_restrict(l.f_max, l.v1); - } - else - { - l.f1_max = l.f0_max = l.f_max; - } + // All the following should be equivalent to + // f0_min = bdd_restrict(f_min, v0); + // f0_max = bdd_restrict(f_max, v0); + // f1_min = bdd_restrict(f_min, v1); + // f1_max = bdd_restrict(f_max, v1); + // but we try to avoid bdd_restrict when possible. + if (v == v_min) + { + l.f0_min = bdd_low(l.f_min); + l.f1_min = bdd_high(l.f_min); + } + else if (v_min < v) + { + l.f0_min = bdd_restrict(l.f_min, v0); + l.f1_min = bdd_restrict(l.f_min, l.v1); + } + else + { + l.f1_min = l.f0_min = l.f_min; + } + if (v == v_max) + { + l.f0_max = bdd_low(l.f_max); + l.f1_max = bdd_high(l.f_max); + } + else if (v_max < v) + { + l.f0_max = bdd_restrict(l.f_max, v0); + l.f1_max = bdd_restrict(l.f_max, l.v1); + } + else + { + l.f1_max = l.f0_max = l.f_max; + } - cube_.push(cube_.top() & v0); - todo_.emplace(l.f0_min - l.f1_max, l.f0_max, l.vars); - } - continue; + cube_.push(cube_.top() & v0); + todo_.emplace(l.f0_min - l.f1_max, l.f0_max, l.vars); + } + continue; - case local_vars::SecondStep: - l.step = local_vars::ThirdStep; - l.g0 = ret_; - cube_.pop(); - cube_.push(cube_.top() & l.v1); - todo_.emplace(l.f1_min - l.f0_max, l.f1_max, l.vars); - continue; + case local_vars::SecondStep: + l.step = local_vars::ThirdStep; + l.g0 = ret_; + cube_.pop(); + cube_.push(cube_.top() & l.v1); + todo_.emplace(l.f1_min - l.f0_max, l.f1_max, l.vars); + continue; - case local_vars::ThirdStep: - l.step = local_vars::FourthStep; - l.g1 = ret_; - cube_.pop(); - { - bdd fs_max = l.f0_max & l.f1_max; - bdd fs_min = fs_max & ((l.f0_min - l.g0) | (l.f1_min - l.g1)); - todo_.emplace(fs_min, fs_max, l.vars); - } - continue; + case local_vars::ThirdStep: + l.step = local_vars::FourthStep; + l.g1 = ret_; + cube_.pop(); + { + bdd fs_max = l.f0_max & l.f1_max; + bdd fs_min = fs_max & ((l.f0_min - l.g0) | (l.f1_min - l.g1)); + todo_.emplace(fs_min, fs_max, l.vars); + } + continue; - case local_vars::FourthStep: - ret_ |= (l.g0 - l.v1) | (l.g1 & l.v1); - todo_.pop(); - continue; - } - SPOT_UNREACHABLE(); + case local_vars::FourthStep: + ret_ |= (l.g0 - l.v1) | (l.g1 & l.v1); + todo_.pop(); + continue; + } + SPOT_UNREACHABLE(); } return bddfalse; } diff --git a/spot/misc/minato.hh b/spot/misc/minato.hh index 3299f1253..d305b059a 100644 --- a/spot/misc/minato.hh +++ b/spot/misc/minato.hh @@ -91,7 +91,7 @@ namespace spot bdd f1_min, f1_max; bdd g0, g1; local_vars(bdd f_min, bdd f_max, bdd vars) - : f_min(f_min), f_max(f_max), step(FirstStep), vars(vars) {} + : f_min(f_min), f_max(f_max), step(FirstStep), vars(vars) {} }; std::stack todo_; std::stack cube_; diff --git a/spot/misc/mspool.hh b/spot/misc/mspool.hh index 457f96fe2..8df955b3d 100644 --- a/spot/misc/mspool.hh +++ b/spot/misc/mspool.hh @@ -43,17 +43,17 @@ namespace spot ~multiple_size_pool() { while (chunklist_) - { - chunk_* prev = chunklist_->prev; - free(chunklist_); - chunklist_ = prev; - } + { + chunk_* prev = chunklist_->prev; + free(chunklist_); + chunklist_ = prev; + } } size_t fixsize(size_t size) const { if (size < sizeof(block_)) - size = sizeof(block_); + size = sizeof(block_); return (size + alignment_ - 1) & ~(alignment_ - 1); } @@ -67,28 +67,28 @@ namespace spot block_*& f = freelist_[size]; // If we have free blocks available, return the first one. if (f) - { - block_* first = f; - f = f->next; - return first; - } + { + block_* first = f; + f = f->next; + return first; + } // Else, create a block out of the last chunk of allocated // memory. // If all the last chunk has been used, allocate one more. if (free_start_ + size > free_end_) - { - const size_t requested = (size > 128 ? size : 128) * 8192 - 64; - chunk_* c = reinterpret_cast(malloc(requested)); - if (!c) - throw std::bad_alloc(); - c->prev = chunklist_; - chunklist_ = c; + { + const size_t requested = (size > 128 ? size : 128) * 8192 - 64; + chunk_* c = reinterpret_cast(malloc(requested)); + if (!c) + throw std::bad_alloc(); + c->prev = chunklist_; + chunklist_ = c; - free_start_ = c->data_ + size; - free_end_ = c->data_ + requested; - } + free_start_ = c->data_ + size; + free_end_ = c->data_ + requested; + } void* res = free_start_; free_start_ += size; diff --git a/spot/misc/optionmap.cc b/spot/misc/optionmap.cc index 95f544681..0aa7eae57 100644 --- a/spot/misc/optionmap.cc +++ b/spot/misc/optionmap.cc @@ -33,96 +33,96 @@ namespace spot { while (*options) { - // Skip leading separators. - while (*options && strchr(" \t\n,;", *options)) - ++options; + // Skip leading separators. + while (*options && strchr(" \t\n,;", *options)) + ++options; - // `!foo' is a shorthand for `foo=0'. - const char* negated = nullptr; - if (*options == '!') - { - // Skip spaces. - while (*options && strchr(" \t\n", *options)) - ++options; - negated = options++; - } + // `!foo' is a shorthand for `foo=0'. + const char* negated = nullptr; + if (*options == '!') + { + // Skip spaces. + while (*options && strchr(" \t\n", *options)) + ++options; + negated = options++; + } - if (!*options) - { - if (negated) - return negated; - else - break; - } + if (!*options) + { + if (negated) + return negated; + else + break; + } - const char* name_start = options; + const char* name_start = options; - // Find the end of the name. - while (*options && !strchr(", \t\n;=", *options)) - ++options; + // Find the end of the name. + while (*options && !strchr(", \t\n;=", *options)) + ++options; - std::string name(name_start, options); + std::string name(name_start, options); - // Skip spaces. - while (*options && strchr(" \t\n", *options)) - ++options; + // Skip spaces. + while (*options && strchr(" \t\n", *options)) + ++options; - if (*options != '=') - { - options_[name] = (negated ? 0 : 1); - } - else if (negated) - { - return negated; - } - else - { - ++options; - // Skip spaces. - while (*options && strchr(" \t\n", *options)) - ++options; - if (!*options) - return name_start; + if (*options != '=') + { + options_[name] = (negated ? 0 : 1); + } + else if (negated) + { + return negated; + } + else + { + ++options; + // Skip spaces. + while (*options && strchr(" \t\n", *options)) + ++options; + if (!*options) + return name_start; - if (*options == '\'' || *options == '"') - { - auto sep = *options; - auto start = options + 1; - do - ++options; - while (*options && *options != sep); - if (*options != sep) - return start - 1; - std::string val(start, options); - options_str_[name] = val; - if (*options) - ++options; - } - else - { - char* val_end; - int val = strtol(options, &val_end, 10); - if (val_end == options) - return name_start; + if (*options == '\'' || *options == '"') + { + auto sep = *options; + auto start = options + 1; + do + ++options; + while (*options && *options != sep); + if (*options != sep) + return start - 1; + std::string val(start, options); + options_str_[name] = val; + if (*options) + ++options; + } + else + { + char* val_end; + int val = strtol(options, &val_end, 10); + if (val_end == options) + return name_start; - if (*val_end == 'K') - { - val *= 1024; - ++val_end; - } - else if (*val_end == 'M') - { - val *= 1024 * 1024; - ++val_end; - } - else if (*val_end && !strchr(" \t\n,;", *val_end)) - { - return options; - } - options = val_end; - options_[name] = val; - } - } + if (*val_end == 'K') + { + val *= 1024; + ++val_end; + } + else if (*val_end == 'M') + { + val *= 1024 * 1024; + ++val_end; + } + else if (*val_end && !strchr(" \t\n,;", *val_end)) + { + return options; + } + options = val_end; + options_[name] = val; + } + } } return nullptr; } diff --git a/spot/misc/optionmap.hh b/spot/misc/optionmap.hh index 464f4cbe0..7e4114b84 100644 --- a/spot/misc/optionmap.hh +++ b/spot/misc/optionmap.hh @@ -84,7 +84,7 @@ namespace spot /// \return The previous value associated to \a option if declared, /// or \a def otherwise. std::string set_str(const char* option, - std::string val, std::string def = {}); + std::string val, std::string def = {}); /// Acquire all the settings of \a o. void set(const option_map& o); diff --git a/spot/misc/random.cc b/spot/misc/random.cc index bcddfc71d..7c30e979d 100644 --- a/spot/misc/random.cc +++ b/spot/misc/random.cc @@ -96,8 +96,8 @@ namespace spot if (has_next) { - has_next = false; - return next; + has_next = false; + return next; } double x; @@ -105,9 +105,9 @@ namespace spot double r; do { - x = 2.0 * drand() - 1.0; - y = 2.0 * drand() - 1.0; - r = x * x + y * y; + x = 2.0 * drand() - 1.0; + y = 2.0 * drand() - 1.0; + r = x * x + y * y; } while (r >= 1.0 || r == 0.0); r = sqrt(-2 * log(r) / r); @@ -124,8 +124,8 @@ namespace spot while (s < p) { - s -= log(1.0 - drand()); - ++x; + s -= log(1.0 - drand()); + ++x; } return x - 1; } diff --git a/spot/misc/random.hh b/spot/misc/random.hh index bc156177b..08fd59069 100644 --- a/spot/misc/random.hh +++ b/spot/misc/random.hh @@ -97,12 +97,12 @@ namespace spot rand() const { for (;;) - { - int x = round(gen() * s_ + m_); - if (x < 0) - continue; + { + int x = round(gen() * s_ + m_); + if (x < 0) + continue; if (x <= n_) - return x; + return x; } SPOT_UNREACHABLE(); return 0; @@ -128,11 +128,11 @@ namespace spot auto d = std::distance(first, last); if (d > 1) { - for (--last; first < last; ++first, --d) - { - auto i = mrand(d); - std::swap(*first, *(first + i)); - } + for (--last; first < last; ++first, --d) + { + auto i = mrand(d); + std::swap(*first, *(first + i)); + } } } /// @} diff --git a/spot/misc/satsolver.cc b/spot/misc/satsolver.cc index 8161ee759..7c196b241 100644 --- a/spot/misc/satsolver.cc +++ b/spot/misc/satsolver.cc @@ -37,48 +37,48 @@ namespace spot satsolver_command() { - satsolver = getenv("SPOT_SATSOLVER"); - if (!satsolver) - { - satsolver = "glucose -verb=0 -model %I >%O"; - return; - } - prime(satsolver); - if (!has('I')) - throw std::runtime_error("SPOT_SATSOLVER should contain %I to " - "indicate how to use the input filename."); - if (!has('O')) - throw std::runtime_error("SPOT_SATSOLVER should contain %O to " - "indicate how to use the output filename."); + satsolver = getenv("SPOT_SATSOLVER"); + if (!satsolver) + { + satsolver = "glucose -verb=0 -model %I >%O"; + return; + } + prime(satsolver); + if (!has('I')) + throw std::runtime_error("SPOT_SATSOLVER should contain %I to " + "indicate how to use the input filename."); + if (!has('O')) + throw std::runtime_error("SPOT_SATSOLVER should contain %O to " + "indicate how to use the output filename."); } int run(printable* in, printable* out) { - declare('I', in); - declare('O', out); - std::ostringstream s; - format(s, satsolver); - int res = system(s.str().c_str()); - if (res < 0 || (WIFEXITED(res) && WEXITSTATUS(res) == 127)) - { - s << ": failed to execute"; - throw std::runtime_error(s.str()); - } - // For POSIX shells, "The exit status of a command that - // terminated because it received a signal shall be reported - // as greater than 128." - if (WIFEXITED(res) && WEXITSTATUS(res) >= 128) - { - s << ": terminated by signal"; - throw std::runtime_error(s.str()); - } - if (WIFSIGNALED(res)) - { - s << ": terminated by signal " << WTERMSIG(res); - throw std::runtime_error(s.str()); - } - return res; + declare('I', in); + declare('O', out); + std::ostringstream s; + format(s, satsolver); + int res = system(s.str().c_str()); + if (res < 0 || (WIFEXITED(res) && WEXITSTATUS(res) == 127)) + { + s << ": failed to execute"; + throw std::runtime_error(s.str()); + } + // For POSIX shells, "The exit status of a command that + // terminated because it received a signal shall be reported + // as greater than 128." + if (WIFEXITED(res) && WEXITSTATUS(res) >= 128) + { + s << ": terminated by signal"; + throw std::runtime_error(s.str()); + } + if (WIFSIGNALED(res)) + { + s << ": terminated by signal " << WTERMSIG(res); + throw std::runtime_error(s.str()); + } + return res; } }; } @@ -96,25 +96,25 @@ namespace spot int c; while ((c = in->get()) != EOF) { - // If a line does not start with 'v ', ignore it. - if (c != 'v' || in->get() != ' ') - { - in->ignore(std::numeric_limits::max(), '\n'); - continue; - } - // Otherwise, read integers one by one. - int i; - while (*in >> i) - { - if (i == 0) - goto done; - sol.push_back(i); - } - if (!in->eof()) - // If we haven't reached end-of-file, then we just attempted - // to extract something that wasn't an integer. Clear the - // fail bit so that will loop over. - in->clear(); + // If a line does not start with 'v ', ignore it. + if (c != 'v' || in->get() != ' ') + { + in->ignore(std::numeric_limits::max(), '\n'); + continue; + } + // Otherwise, read integers one by one. + int i; + while (*in >> i) + { + if (i == 0) + goto done; + sol.push_back(i); + } + if (!in->eof()) + // If we haven't reached end-of-file, then we just attempted + // to extract something that wasn't an integer. Clear the + // fail bit so that will loop over. + in->clear(); } done: if (in != &std::cin) @@ -149,7 +149,7 @@ namespace spot satsolver::solution_pair satsolver::get_solution() { - delete cnf_stream_; // Close the file. + delete cnf_stream_; // Close the file. cnf_stream_ = nullptr; temporary_file* output = create_tmpfile("sat-", ".out"); diff --git a/spot/misc/satsolver.hh b/spot/misc/satsolver.hh index 434b679e9..75ef7d0de 100644 --- a/spot/misc/satsolver.hh +++ b/spot/misc/satsolver.hh @@ -43,7 +43,7 @@ namespace spot void check() const { if (count_ < 0) - throw std::runtime_error("too many SAT clauses (more than INT_MAX)"); + throw std::runtime_error("too many SAT clauses (more than INT_MAX)"); } clause_counter& operator++() diff --git a/spot/misc/timer.cc b/spot/misc/timer.cc index 2598c4c9f..e1e98c74d 100644 --- a/spot/misc/timer.cc +++ b/spot/misc/timer.cc @@ -37,8 +37,8 @@ namespace spot time_info total; for (tm_type::const_iterator i = tm.begin(); i != tm.end(); ++i) { - total.utime += i->second.first.utime(); - total.stime += i->second.first.stime(); + total.utime += i->second.first.utime(); + total.stime += i->second.first.stime(); } clock_t grand_total = total.utime + total.stime; @@ -52,30 +52,30 @@ namespace spot << std::endl; for (tm_type::const_iterator i = tm.begin(); i != tm.end(); ++i) { - // truncate long keys - std::string name = i->first; - if (name.size() > 22) - name.erase(22); + // truncate long keys + std::string name = i->first; + if (name.size() > 22) + name.erase(22); - const spot::timer& t = i->second.first; - const char* sep = t.is_running() ? "+|" : " |"; + const spot::timer& t = i->second.first; + const char* sep = t.is_running() ? "+|" : " |"; - os << std::setw(22) << name << sep - << std::setw(6) << t.utime() << ' ' - << std::setw(8) << (total.utime ? - 100.0 * t.utime() / total.utime : 0.) - << sep - << std::setw(6) << t.stime() << ' ' - << std::setw(8) << (total.stime ? - 100.0 * t.stime() / total.stime : 0.) - << sep - << std::setw(6) << t.utime() + t.stime() << ' ' - << std::setw(8) << (grand_total ? - (100.0 * (t.utime() + t.stime()) / - grand_total) : 0.) - << sep - << std::setw(4) << i->second.second - << std::endl; + os << std::setw(22) << name << sep + << std::setw(6) << t.utime() << ' ' + << std::setw(8) << (total.utime ? + 100.0 * t.utime() / total.utime : 0.) + << sep + << std::setw(6) << t.stime() << ' ' + << std::setw(8) << (total.stime ? + 100.0 * t.stime() / total.stime : 0.) + << sep + << std::setw(6) << t.utime() + t.stime() << ' ' + << std::setw(8) << (grand_total ? + (100.0 * (t.utime() + t.stime()) / + grand_total) : 0.) + << sep + << std::setw(4) << i->second.second + << std::endl; } os << std::setw(79) << std::setfill('-') << "" << std::setfill(' ') << std::endl diff --git a/spot/misc/timer.hh b/spot/misc/timer.hh index a0e3ffaff..f7c47bc5a 100644 --- a/spot/misc/timer.hh +++ b/spot/misc/timer.hh @@ -197,7 +197,7 @@ namespace spot assert(i != tm.end()); assert(0 < i->second.second); if (0 == --i->second.second) - tm.erase(i); + tm.erase(i); } /// Return the timer \a name. diff --git a/spot/misc/tmpfile.cc b/spot/misc/tmpfile.cc index 43b5dc103..3f61f3b43 100644 --- a/spot/misc/tmpfile.cc +++ b/spot/misc/tmpfile.cc @@ -35,14 +35,14 @@ namespace spot { const char* res = secure_getenv("SPOT_TMPDIR"); if (res) - return res; + return res; return secure_getenv("TMPDIR"); } static int create_temporary_file(const char* prefix, - const char* suffix, - char** name) + const char* suffix, + char** name) throw(std::bad_alloc, std::runtime_error) { static const char* tmpdir = get_tmpdir(); @@ -51,30 +51,30 @@ namespace spot size_t len = strlen(prefix); size_t slen = 0; if (suffix) - len += slen = strlen(suffix); + len += slen = strlen(suffix); char* x = *name = static_cast(malloc(tmpdirlen + 1 + len + 6 + 1)); if (!x) - throw std::bad_alloc(); + throw std::bad_alloc(); if (tmpdir) - { - x = stpcpy(x, tmpdir); - if (x[-1] != '/') - *x++ = '/'; - } + { + x = stpcpy(x, tmpdir); + if (x[-1] != '/') + *x++ = '/'; + } x = stpcpy(x, prefix); x = stpcpy(x, "XXXXXX"); int fd; if (suffix) - { - stpcpy(x, suffix); - fd = mkstemps(*name, slen); - } + { + stpcpy(x, suffix); + fd = mkstemps(*name, slen); + } else - { - fd = mkstemp(*name); - } + { + fd = mkstemp(*name); + } if (fd < 0) - throw std::runtime_error(std::string("failed to create ") + *name); + throw std::runtime_error(std::string("failed to create ") + *name); return fd; } } diff --git a/spot/misc/trival.hh b/spot/misc/trival.hh index f9ad14544..36f0f8eef 100644 --- a/spot/misc/trival.hh +++ b/spot/misc/trival.hh @@ -113,8 +113,8 @@ namespace spot constexpr trival operator!() const { return trival((val_ == yes_value) ? no_value : - (val_ == no_value) ? yes_value : - maybe_value); + (val_ == no_value) ? yes_value : + maybe_value); } }; @@ -171,8 +171,8 @@ namespace spot inline std::ostream& operator<<(std::ostream& os, trival v) { return os << ((v.val() == trival::no_value) ? "no" - : (v.val() == trival::maybe_value) ? "maybe" - : "yes"); + : (v.val() == trival::maybe_value) ? "maybe" + : "yes"); } /// @} diff --git a/spot/parseaut/fmterror.cc b/spot/parseaut/fmterror.cc index 936ce2f4f..9175a263e 100644 --- a/spot/parseaut/fmterror.cc +++ b/spot/parseaut/fmterror.cc @@ -29,11 +29,11 @@ namespace spot spot::parse_aut_error_list::iterator it; for (auto& err : errors) { - if (!filename.empty() && filename != "-") - os << filename << ':'; - os << err.first << ": "; - os << err.second << std::endl; - printed = true; + if (!filename.empty() && filename != "-") + os << filename << ':'; + os << err.first << ": "; + os << err.second << std::endl; + printed = true; } return printed; } diff --git a/spot/parseaut/parsedecl.hh b/spot/parseaut/parsedecl.hh index 45a830a71..a7b80802a 100644 --- a/spot/parseaut/parsedecl.hh +++ b/spot/parseaut/parsedecl.hh @@ -25,8 +25,8 @@ # define YY_DECL \ int hoayylex(hoayy::parser::semantic_type *yylval, \ - spot::location *yylloc, \ - spot::parse_aut_error_list& error_list) + spot::location *yylloc, \ + spot::parse_aut_error_list& error_list) YY_DECL; namespace spot diff --git a/spot/parseaut/public.hh b/spot/parseaut/public.hh index 6ccf6ee88..259371cef 100644 --- a/spot/parseaut/public.hh +++ b/spot/parseaut/public.hh @@ -91,11 +91,11 @@ namespace spot struct automaton_parser_options final { - bool ignore_abort = false; ///< Skip aborted automata - bool debug = false; ///< Run the parser in debug mode? - bool trust_hoa = true; ///< Trust properties in HOA files - bool raise_errors = false; ///< Raise errors as exceptions. - bool want_kripke = false; ///< Parse as a Kripke structure. + bool ignore_abort = false; ///< Skip aborted automata + bool debug = false; ///< Run the parser in debug mode? + bool trust_hoa = true; ///< Trust properties in HOA files + bool raise_errors = false; ///< Raise errors as exceptions. + bool want_kripke = false; ///< Parse as a Kripke structure. }; /// \brief Parse a stream of automata @@ -128,7 +128,7 @@ namespace spot /// \param filename The file to read from. /// \param opts Parser options. automaton_stream_parser(const std::string& filename, - automaton_parser_options opts = {}); + automaton_parser_options opts = {}); /// \brief Parse from an already opened file descriptor. /// @@ -136,7 +136,7 @@ namespace spot /// \param filename What to display in error messages. /// \param opts Parser options. automaton_stream_parser(int fd, const std::string& filename, - automaton_parser_options opts = {}); + automaton_parser_options opts = {}); /// \brief Parse from a buffer /// @@ -144,8 +144,8 @@ namespace spot /// \param filename What to display in error messages. /// \param opts Parser options. automaton_stream_parser(const char* data, - const std::string& filename, - automaton_parser_options opts = {}); + const std::string& filename, + automaton_parser_options opts = {}); ~automaton_stream_parser(); @@ -165,8 +165,8 @@ namespace spot /// /// \warning This function is not reentrant. parsed_aut_ptr parse(const bdd_dict_ptr& dict, - environment& env = - default_environment::instance()); + environment& env = + default_environment::instance()); }; /// \brief Read the first spot::twa_graph from a file. @@ -187,8 +187,8 @@ namespace spot /// \warning This function is not reentrant. SPOT_API parsed_aut_ptr parse_aut(const std::string& filename, - const bdd_dict_ptr& dict, - environment& env = default_environment::instance(), - automaton_parser_options opts = {}); + const bdd_dict_ptr& dict, + environment& env = default_environment::instance(), + automaton_parser_options opts = {}); /// @} } diff --git a/spot/parsetl/fmterror.cc b/spot/parsetl/fmterror.cc index 574ba2837..e7a231603 100644 --- a/spot/parsetl/fmterror.cc +++ b/spot/parsetl/fmterror.cc @@ -30,7 +30,7 @@ namespace spot { void fix_utf8_locations(const std::string& ltl_string, - parse_error_list& error_list) + parse_error_list& error_list) { // LUT to convert byte positions to utf8 positions. // (The +2 is to account for position 0, not used, @@ -42,15 +42,15 @@ namespace spot std::string::const_iterator i = b; std::string::const_iterator e = ltl_string.end(); - unsigned n = 0; // number of current utf8 character - unsigned prev = 0; // last byte of previous utf8 character + unsigned n = 0; // number of current utf8 character + unsigned prev = 0; // last byte of previous utf8 character while (i != e) { - utf8::next(i, e); - ++n; - unsigned d = std::distance(b, i); - while (prev < d) - b2u[++prev] = n; + utf8::next(i, e); + ++n; + unsigned d = std::distance(b, i); + while (prev < d) + b2u[++prev] = n; } b2u[++prev] = ++n; @@ -58,9 +58,9 @@ namespace spot parse_error_list::iterator it; for (it = error_list.begin(); it != error_list.end(); ++it) { - location& l = it->first; - l.begin.column = b2u[l.begin.column]; - l.end.column = b2u[l.end.column]; + location& l = it->first; + l.begin.column = b2u[l.begin.column]; + l.end.column = b2u[l.end.column]; } } @@ -68,45 +68,45 @@ namespace spot { static bool format_parse_errors_aux(std::ostream& os, - const std::string& ltl_string, - const parse_error_list& error_list, - unsigned shift) + const std::string& ltl_string, + const parse_error_list& error_list, + unsigned shift) { bool printed = false; for (auto it: error_list) - { - os << ">>> " << ltl_string << '\n'; - const location& l = it.first; + { + os << ">>> " << ltl_string << '\n'; + const location& l = it.first; - unsigned n = 1; - for (; n < 4 + l.begin.column + shift; ++n) - os << ' '; - // Write at least one '^', even if begin==end. - os << '^'; - ++n; - for (; n < 4 + l.end.column + shift; ++n) - os << '^'; - os << '\n' << it.second << "\n\n"; - printed = true; - } + unsigned n = 1; + for (; n < 4 + l.begin.column + shift; ++n) + os << ' '; + // Write at least one '^', even if begin==end. + os << '^'; + ++n; + for (; n < 4 + l.end.column + shift; ++n) + os << '^'; + os << '\n' << it.second << "\n\n"; + printed = true; + } return printed; } } bool parsed_formula::format_errors(std::ostream& os, - const std::string& real_input, - unsigned shift) + const std::string& real_input, + unsigned shift) { if (utf8::is_valid(input.begin(), input.end())) { - parse_error_list fixed = errors; - fix_utf8_locations(input, fixed); - return format_parse_errors_aux(os, real_input, fixed, shift); + parse_error_list fixed = errors; + fix_utf8_locations(input, fixed); + return format_parse_errors_aux(os, real_input, fixed, shift); } else { - return format_parse_errors_aux(os, real_input, errors, shift); + return format_parse_errors_aux(os, real_input, errors, shift); } } diff --git a/spot/parsetl/parsedecl.hh b/spot/parsetl/parsedecl.hh index 1e023accc..55e5efdc6 100644 --- a/spot/parsetl/parsedecl.hh +++ b/spot/parsetl/parsedecl.hh @@ -27,8 +27,8 @@ # define YY_DECL \ int tlyylex (tlyy::parser::semantic_type *yylval, \ - spot::location *yylloc, \ - spot::parse_error_list& error_list) + spot::location *yylloc, \ + spot::parse_error_list& error_list) YY_DECL; void flex_set_buffer(const std::string& buf, int start_tok, bool lenient); diff --git a/spot/priv/accmap.hh b/spot/priv/accmap.hh index 5340526a2..2030fb962 100644 --- a/spot/priv/accmap.hh +++ b/spot/priv/accmap.hh @@ -53,7 +53,7 @@ namespace spot { auto i = map_.find(name); if (i != map_.end()) - return true; + return true; auto v = aut_->acc().add_set(); map_[name] = v; return true; @@ -63,7 +63,7 @@ namespace spot { auto p = map_.find(name); if (p == map_.end()) - return std::make_pair(false, 0U); + return std::make_pair(false, 0U); return std::make_pair(true, acc_cond::mark_t({p->second})); } }; @@ -83,9 +83,9 @@ namespace spot std::pair lookup(unsigned n) { if (n < aut_->acc().num_sets()) - return std::make_pair(true, acc_cond::mark_t({n})); + return std::make_pair(true, acc_cond::mark_t({n})); else - return std::make_pair(false, 0U); + return std::make_pair(false, 0U); } }; @@ -106,13 +106,13 @@ namespace spot { auto p = map_.find(n); if (p != map_.end()) - return std::make_pair(true, p->second); + return std::make_pair(true, p->second); if (used_ < aut_->acc().num_sets()) - { - auto res = acc_cond::mark_t({used_++}); - map_[n] = res; - return std::make_pair(true, res); - } + { + auto res = acc_cond::mark_t({used_++}); + map_[n] = res; + return std::make_pair(true, res); + } return std::make_pair(false, 0U); } }; diff --git a/spot/priv/bddalloc.cc b/spot/priv/bddalloc.cc index 887ac1819..60d028fb9 100644 --- a/spot/priv/bddalloc.cc +++ b/spot/priv/bddalloc.cc @@ -67,15 +67,15 @@ namespace spot // externally), use the new variables. if (lvarnum < varnum) { - more -= varnum - lvarnum; - lvarnum = varnum; + more -= varnum - lvarnum; + lvarnum = varnum; } // If we still need more variable, do allocate them. if (more > 0) { - bdd_extvarnum(more); - varnum += more; - lvarnum = varnum; + bdd_extvarnum(more); + varnum += more; + lvarnum = varnum; } } @@ -98,19 +98,19 @@ namespace spot // of the variable space, allocate just the difference. if (!fl.empty() && fl.back().first + fl.back().second == lvarnum) { - int res = fl.back().first; - int endvar = fl.back().second; - assert(n > endvar); - extvarnum(n - endvar); - fl.pop_back(); - return res; + int res = fl.back().first; + int endvar = fl.back().second; + assert(n > endvar); + extvarnum(n - endvar); + fl.pop_back(); + return res; } else { - // Otherwise, allocate as much variables as we need. - int res = lvarnum; - extvarnum(n); - return res; + // Otherwise, allocate as much variables as we need. + int res = lvarnum; + extvarnum(n); + return res; } } } diff --git a/spot/priv/freelist.cc b/spot/priv/freelist.cc index 3f505b46b..4b806afc9 100644 --- a/spot/priv/freelist.cc +++ b/spot/priv/freelist.cc @@ -41,24 +41,24 @@ namespace spot free_list_type::iterator cur; for (cur = fl.begin(); cur != fl.end(); ++cur) { - if (cur->second < n) - continue; - if (n == cur->second) - { - best = cur; - break; - } - if (best == fl.end() - || cur->second < best->second) - best = cur; + if (cur->second < n) + continue; + if (n == cur->second) + { + best = cur; + break; + } + if (best == fl.end() + || cur->second < best->second) + best = cur; } // We have found enough free variables. if (best != fl.end()) { - int result = best->first; - remove(best, result, n); - return result; + int result = best->first; + remove(best, result, n); + return result; } // We haven't found enough adjacent free variables; @@ -73,67 +73,67 @@ namespace spot int end = base + n; for (cur = fl.begin(); cur != fl.end(); ++cur) { - int cend = cur->first + cur->second; - // cur [...] - // to insert [...] - // ----------------------- - // result [...] [...] - // (Insert a new range, unconnected.) - if (cur->first > end) - { - break; - } - // cur [...] - // to insert [...] - // ----------------------- - // result unknown : we should look at the rest of the freelist. - else if (base > cend) - { - continue; - } - // cur [....[ [......[ - // to insert [....[ [..[ - // ---------------------------------- - // result [......[ [......[ - else if (cur->first <= base) - { - if (cend >= end) - // second case : nothing to do - return; - // cur->second is set below. - } - // cur [....[ [..[ - // to insert [....[ [.......[ - // ---------------------------------- - // result [......[ [.......[ - else - { - cur->first = base; - // cur->second is set below. - } + int cend = cur->first + cur->second; + // cur [...] + // to insert [...] + // ----------------------- + // result [...] [...] + // (Insert a new range, unconnected.) + if (cur->first > end) + { + break; + } + // cur [...] + // to insert [...] + // ----------------------- + // result unknown : we should look at the rest of the freelist. + else if (base > cend) + { + continue; + } + // cur [....[ [......[ + // to insert [....[ [..[ + // ---------------------------------- + // result [......[ [......[ + else if (cur->first <= base) + { + if (cend >= end) + // second case : nothing to do + return; + // cur->second is set below. + } + // cur [....[ [..[ + // to insert [....[ [.......[ + // ---------------------------------- + // result [......[ [.......[ + else + { + cur->first = base; + // cur->second is set below. + } - // We get here in one of these three situations: - // - // cur [....[ [....[ [..[ - // to insert [....[ [....[ [.......[ - // ------------------------------------------- - // result [......[ [......[ [.......[ - // - // cur->first is already set, be cur->second has yet to be. - end = std::max(cend, end); - cur->second = end - cur->first; - // Since we have extended the current range, maybe the next - // items on the list should be merged. - free_list_type::iterator next = cur; - ++next; - while (next != fl.end() && next->first <= end) - { - end = std::max(next->first + next->second, end); - cur->second = end - cur->first; - free_list_type::iterator next2 = next++; - fl.erase(next2); - } - return; + // We get here in one of these three situations: + // + // cur [....[ [....[ [..[ + // to insert [....[ [....[ [.......[ + // ------------------------------------------- + // result [......[ [......[ [.......[ + // + // cur->first is already set, be cur->second has yet to be. + end = std::max(cend, end); + cur->second = end - cur->first; + // Since we have extended the current range, maybe the next + // items on the list should be merged. + free_list_type::iterator next = cur; + ++next; + while (next != fl.end() && next->first <= end) + { + end = std::max(next->first + next->second, end); + cur->second = end - cur->first; + free_list_type::iterator next2 = next++; + fl.erase(next2); + } + return; } // We reach this place either because a new unconnected range @@ -148,15 +148,15 @@ namespace spot int end = base + n; while (cur != fl.end() && cur->first < end) { - int cend = cur->first + cur->second; - // Remove may invalidate the current iterator, so advance it first. - free_list_type::iterator old = cur++; - if (cend >= base) - { - int newbase = std::max(base, old->first); - int q = std::min(cend, end) - newbase; - remove(old, newbase, q); - } + int cend = cur->first + cur->second; + // Remove may invalidate the current iterator, so advance it first. + free_list_type::iterator old = cur++; + if (cend >= base) + { + int newbase = std::max(base, old->first); + int q = std::min(cend, end) - newbase; + remove(old, newbase, q); + } } } @@ -165,31 +165,31 @@ namespace spot { if (base == i->first) { - // Removing at the beginning of the range - i->second -= n; - assert(i->second >= 0); - // Erase the range if it's now empty. - if (i->second == 0) - fl.erase(i); - else - i->first += n; + // Removing at the beginning of the range + i->second -= n; + assert(i->second >= 0); + // Erase the range if it's now empty. + if (i->second == 0) + fl.erase(i); + else + i->first += n; } else if (base + n == i->first + i->second) { - // Removing at the end of the range - i->second -= n; - assert(i->second > 0); // cannot be empty because base != i->first + // Removing at the end of the range + i->second -= n; + assert(i->second > 0); // cannot be empty because base != i->first } else { - // Removing in the middle of a range. - int b1 = i->first; - int n1 = base - i->first; - int n2 = i->first + i->second - base - n; - assert(n1 > 0); - assert(n2 > 0); - *i = pos_lenght_pair(base + n, n2); - fl.insert(i, pos_lenght_pair(b1, n1)); + // Removing in the middle of a range. + int b1 = i->first; + int n1 = base - i->first; + int n2 = i->first + i->second - base - n; + assert(n1 > 0); + assert(n2 > 0); + *i = pos_lenght_pair(base + n, n2); + fl.insert(i, pos_lenght_pair(b1, n1)); } } diff --git a/spot/priv/trim.cc b/spot/priv/trim.cc index 2464daa17..12b3c95e6 100644 --- a/spot/priv/trim.cc +++ b/spot/priv/trim.cc @@ -29,11 +29,11 @@ namespace spot trim(std::string& str) { str.erase(std::find_if(str.rbegin(), str.rend(), - std::not1(std::ptr_fun - (std::isspace))).base(), - str.end()); + std::not1(std::ptr_fun + (std::isspace))).base(), + str.end()); str.erase(str.begin(), - std::find_if(str.begin(), str.end(), - std::not1(std::ptr_fun(std::isspace)))); + std::find_if(str.begin(), str.end(), + std::not1(std::ptr_fun(std::isspace)))); } } diff --git a/spot/priv/weight.cc b/spot/priv/weight.cc index 80938889d..c1cc6420e 100644 --- a/spot/priv/weight.cc +++ b/spot/priv/weight.cc @@ -42,7 +42,7 @@ namespace spot { for (auto s: a.sets()) if (m[s] > 0) - --m[s]; + --m[s]; return *this; } @@ -52,7 +52,7 @@ namespace spot std::vector res; for (unsigned n = 0; n < max; ++n) if (m[n] > w.m[n]) - res.push_back(n); + res.push_back(n); return acc_cond::mark_t(res.begin(), res.end()); } diff --git a/spot/priv/weight.hh b/spot/priv/weight.hh index f125dc590..b861ba189 100644 --- a/spot/priv/weight.hh +++ b/spot/priv/weight.hh @@ -48,7 +48,7 @@ namespace spot /// the corresponding counter in w. acc_cond::mark_t diff(const acc_cond& acc, const weight& w) const; friend std::ostream& operator<<(std::ostream& os, - const weight& w); + const weight& w); private: std::vector m; diff --git a/spot/ta/taexplicit.cc b/spot/ta/taexplicit.cc index 2d571b9da..393d6fc26 100644 --- a/spot/ta/taexplicit.cc +++ b/spot/ta/taexplicit.cc @@ -276,7 +276,7 @@ namespace spot bool is_stuttering_transition = (get_tgba_condition() == (dest)->get_tgba_condition()); bool dest_is_livelock_accepting = - dest->is_livelock_accepting_state(); + dest->is_livelock_accepting_state(); //Before deleting stuttering transitions, propaged back livelock //and initial state's properties @@ -319,7 +319,7 @@ namespace spot // they are not cloned. if (trans) for (auto& t: *trans) - delete t; + delete t; delete trans; std::unordered_map >::iterator i = @@ -338,8 +338,8 @@ namespace spot ta_explicit::ta_explicit(const const_twa_ptr& tgba, - unsigned n_acc, - state_ta_explicit* artificial_initial_state): + unsigned n_acc, + state_ta_explicit* artificial_initial_state): ta(tgba->get_dict()), tgba_(tgba), artificial_initial_state_(artificial_initial_state) @@ -351,7 +351,7 @@ namespace spot { auto is = add_state(artificial_initial_state); assert(is == artificial_initial_state); - (void)is; + (void)is; } } @@ -361,8 +361,8 @@ namespace spot for (it = states_set_.begin(); it != states_set_.end(); ++it) { auto* s = const_cast - (down_cast(*it)); - assert(s); + (down_cast(*it)); + assert(s); s->free_transitions(); s->get_tgba_state()->destroy(); delete s; @@ -390,11 +390,11 @@ namespace spot auto add_state = initial_states_set_.insert(s); if (get_artificial_initial_state()) if (add_state.second) - { - auto i = - down_cast(get_artificial_initial_state()); - create_transition(i, condition, 0U, s); - } + { + auto i = + down_cast(get_artificial_initial_state()); + create_transition(i, condition, 0U, s); + } } void @@ -411,9 +411,9 @@ namespace spot void ta_explicit::create_transition(state_ta_explicit* source, bdd condition, - acc_cond::mark_t acceptance_conditions, - const state_ta_explicit* dest, - bool add_at_beginning) + acc_cond::mark_t acceptance_conditions, + const state_ta_explicit* dest, + bool add_at_beginning) { state_ta_explicit::transition* t = new state_ta_explicit::transition; t->dest = dest; diff --git a/spot/ta/taexplicit.hh b/spot/ta/taexplicit.hh index a2f836c30..2778d7628 100644 --- a/spot/ta/taexplicit.hh +++ b/spot/ta/taexplicit.hh @@ -41,8 +41,8 @@ namespace spot { public: ta_explicit(const const_twa_ptr& tgba, - unsigned n_acc, - state_ta_explicit* artificial_initial_state = nullptr); + unsigned n_acc, + state_ta_explicit* artificial_initial_state = nullptr); const_twa_ptr get_tgba() const; @@ -55,9 +55,9 @@ namespace spot void create_transition(state_ta_explicit* source, bdd condition, - acc_cond::mark_t acceptance_conditions, - const state_ta_explicit* dest, - bool add_at_beginning = false); + acc_cond::mark_t acceptance_conditions, + const state_ta_explicit* dest, + bool add_at_beginning = false); void delete_stuttering_transitions(); @@ -142,10 +142,10 @@ namespace spot typedef std::list transitions; state_ta_explicit(const state* tgba_state, const bdd tgba_condition, - bool is_initial_state = false, - bool is_accepting_state = false, - bool is_livelock_accepting_state = false, - transitions* trans = nullptr) : + bool is_initial_state = false, + bool is_accepting_state = false, + bool is_livelock_accepting_state = false, + transitions* trans = nullptr) : tgba_state_(tgba_state), tgba_condition_(tgba_condition), is_initial_state_(is_initial_state), is_accepting_state_( is_accepting_state), is_livelock_accepting_state_( @@ -246,8 +246,8 @@ namespace spot inline ta_explicit_ptr make_ta_explicit(const const_twa_ptr& tgba, - unsigned n_acc, - state_ta_explicit* artificial_initial_state = nullptr) + unsigned n_acc, + state_ta_explicit* artificial_initial_state = nullptr) { return std::make_shared(tgba, n_acc, artificial_initial_state); } diff --git a/spot/ta/taproduct.cc b/spot/ta/taproduct.cc index c57fd3a6d..63748e3a6 100644 --- a/spot/ta/taproduct.cc +++ b/spot/ta/taproduct.cc @@ -67,8 +67,8 @@ namespace spot //////////////////////////////////////////////////////////// // ta_succ_iterator_product ta_succ_iterator_product::ta_succ_iterator_product(const state_ta_product* s, - const ta* t, - const kripke* k) + const ta* t, + const kripke* k) : source_(s), ta_(t), kripke_(k) { kripke_source_condition = kripke_->state_condition(s->get_kripke_state()); @@ -243,7 +243,7 @@ namespace spot ta_product::ta_product(const const_ta_ptr& testing_automata, - const const_kripke_ptr& kripke_structure): + const const_kripke_ptr& kripke_structure): ta(testing_automata->get_dict()), dict_(testing_automata->get_dict()), ta_(testing_automata), @@ -292,9 +292,9 @@ namespace spot for (auto s: ta_init_states_set) if (artificial_initial_state || - (kripke_init_condition == ta_->get_state_condition(s))) - initial_states_set.insert(new state_ta_product(s, - kripke_init->clone())); + (kripke_init_condition == ta_->get_state_condition(s))) + initial_states_set.insert(new state_ta_product(s, + kripke_init->clone())); kripke_init->destroy(); return initial_states_set; @@ -316,8 +316,8 @@ namespace spot const state_ta_product* stp = down_cast (s); assert(s); return new ta_succ_iterator_product_by_changeset(stp, - ta_.get(), kripke_.get(), - changeset); + ta_.get(), kripke_.get(), + changeset); } @@ -402,7 +402,7 @@ namespace spot ta_succ_iterator_product_by_changeset:: ta_succ_iterator_product_by_changeset(const state_ta_product* s, const ta* t, - const kripke* k, bdd changeset) + const kripke* k, bdd changeset) : ta_succ_iterator_product(s, t, k) { current_condition_ = changeset; diff --git a/spot/ta/taproduct.hh b/spot/ta/taproduct.hh index a52eabcb0..32286c63d 100644 --- a/spot/ta/taproduct.hh +++ b/spot/ta/taproduct.hh @@ -131,7 +131,7 @@ namespace spot /// \param testing_automaton The TA component in the product. /// \param kripke_structure The Kripke component in the product. ta_product(const const_ta_ptr& testing_automaton, - const const_kripke_ptr& kripke_structure); + const const_kripke_ptr& kripke_structure); virtual ~ta_product(); @@ -197,7 +197,7 @@ namespace spot typedef std::shared_ptr ta_product_ptr; typedef std::shared_ptr const_ta_product_ptr; inline ta_product_ptr product(const const_ta_ptr& testing_automaton, - const const_kripke_ptr& kripke_structure) + const const_kripke_ptr& kripke_structure) { return std::make_shared(testing_automaton, kripke_structure); } @@ -207,8 +207,8 @@ namespace spot { public: ta_succ_iterator_product_by_changeset(const state_ta_product* s, - const ta* t, const kripke* k, - bdd changeset); + const ta* t, const kripke* k, + bdd changeset); /// \brief Move to the next successor in the Kripke structure void next_kripke_dest(); diff --git a/spot/ta/tgtaexplicit.cc b/spot/ta/tgtaexplicit.cc index 03a41a05d..40af1632e 100644 --- a/spot/ta/tgtaexplicit.cc +++ b/spot/ta/tgtaexplicit.cc @@ -25,8 +25,8 @@ namespace spot { tgta_explicit::tgta_explicit(const const_twa_ptr& tgba, - unsigned n_acc, - state_ta_explicit* artificial_initial_state) : + unsigned n_acc, + state_ta_explicit* artificial_initial_state) : tgta(tgba->get_dict()), ta_(make_ta_explicit(tgba, n_acc, artificial_initial_state)) { diff --git a/spot/ta/tgtaexplicit.hh b/spot/ta/tgtaexplicit.hh index 574fa3490..551f0551e 100644 --- a/spot/ta/tgtaexplicit.hh +++ b/spot/ta/tgtaexplicit.hh @@ -38,8 +38,8 @@ namespace spot { public: tgta_explicit(const const_twa_ptr& tgba, - unsigned n_acc, - state_ta_explicit* artificial_initial_state); + unsigned n_acc, + state_ta_explicit* artificial_initial_state); // tgba interface virtual spot::state* get_init_state() const override; @@ -63,9 +63,9 @@ namespace spot inline tgta_explicit_ptr make_tgta_explicit(const const_twa_ptr& tgba, unsigned n_acc, - state_ta_explicit* artificial_initial_state = nullptr) + state_ta_explicit* artificial_initial_state = nullptr) { return std::make_shared(tgba, n_acc, - artificial_initial_state); + artificial_initial_state); } } diff --git a/spot/ta/tgtaproduct.cc b/spot/ta/tgtaproduct.cc index 017dc5ade..7f16b6c72 100644 --- a/spot/ta/tgtaproduct.cc +++ b/spot/ta/tgtaproduct.cc @@ -44,7 +44,7 @@ namespace spot // tgta_product tgta_product::tgta_product(const const_kripke_ptr& left, - const const_tgta_ptr& right): + const const_tgta_ptr& right): twa_product(left, right) { } @@ -207,7 +207,7 @@ namespace spot kripke_current_dest_state->clone(), tgta_succ_it_->dst(), pool_); current_acceptance_conditions_ - = tgta_succ_it_->acc(); + = tgta_succ_it_->acc(); return true; } diff --git a/spot/ta/tgtaproduct.hh b/spot/ta/tgtaproduct.hh index 36ca271cb..e1bb5d947 100644 --- a/spot/ta/tgtaproduct.hh +++ b/spot/ta/tgtaproduct.hh @@ -33,7 +33,7 @@ namespace spot { public: tgta_product(const const_kripke_ptr& left, - const const_tgta_ptr& right); + const const_tgta_ptr& right); virtual const state* get_init_state() const override; @@ -42,7 +42,7 @@ namespace spot }; inline twa_ptr product(const const_kripke_ptr& left, - const const_tgta_ptr& right) + const const_tgta_ptr& right) { return std::make_shared(left, right); } @@ -52,9 +52,9 @@ namespace spot { public: tgta_succ_iterator_product(const state_product* s, - const const_kripke_ptr& k, - const const_tgta_ptr& tgta, - fixed_size_pool* pool); + const const_kripke_ptr& k, + const const_tgta_ptr& tgta, + fixed_size_pool* pool); virtual ~tgta_succ_iterator_product(); diff --git a/spot/taalgos/dot.cc b/spot/taalgos/dot.cc index fb20cc78a..baf318a48 100644 --- a/spot/taalgos/dot.cc +++ b/spot/taalgos/dot.cc @@ -35,109 +35,109 @@ namespace spot void parse_opts(const char* options) { - const char* orig = options; - while (char c = *options++) - switch (c) - { - case '.': - { - // Copy the value in a string, so future calls to - // parse_opts do not fail if the environment has - // changed. (This matters particularly in an ipython - // notebook, where it is tempting to redefine - // SPOT_DOTDEFAULT.) - static std::string def = []() - { - auto s = getenv("SPOT_DOTDEFAULT"); - return s ? s : ""; - }(); - // Prevent infinite recursions... - if (orig == def.c_str()) - throw std::runtime_error - (std::string("SPOT_DOTDEFAULT should not contain '.'")); - if (!def.empty()) - parse_opts(def.c_str()); - break; - } - case 'A': - opt_hide_sets_ = true; - break; - case 'c': - opt_circles_ = true; - break; - case 'C': - if (*options != '(') - throw std::runtime_error - ("invalid node color specification for print_dot()"); - { - auto* end = strchr(++options, ')'); - if (!end) - throw std::runtime_error - ("invalid node color specification for print_dot()"); - opt_node_color_ = std::string(options, end - options); - options = end + 1; - } - break; - case 'h': - opt_horizontal_ = true; - break; - case 'f': - if (*options != '(') - throw std::runtime_error - (std::string("invalid font specification for dotty()")); - { - auto* end = strchr(++options, ')'); - if (!end) - throw std::runtime_error - (std::string("invalid font specification for dotty()")); - opt_font_ = std::string(options, end - options); - options = end + 1; - } - break; - case 'v': - opt_horizontal_ = false; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case 'a': - case 'b': - case 'B': - case 'e': - case 'n': - case 'N': - case 'o': - case 'r': - case 'R': - case 's': - case 't': - case '+': - case '<': - case '#': - // All these options are implemented by dotty() on TGBA, - // but are not implemented here. We simply ignore them, - // because raising an exception if they are in - // SPOT_DEFAULT would be annoying. - break; - default: - throw std::runtime_error - (std::string("unknown option for dotty(): ") + c); - } + const char* orig = options; + while (char c = *options++) + switch (c) + { + case '.': + { + // Copy the value in a string, so future calls to + // parse_opts do not fail if the environment has + // changed. (This matters particularly in an ipython + // notebook, where it is tempting to redefine + // SPOT_DOTDEFAULT.) + static std::string def = []() + { + auto s = getenv("SPOT_DOTDEFAULT"); + return s ? s : ""; + }(); + // Prevent infinite recursions... + if (orig == def.c_str()) + throw std::runtime_error + (std::string("SPOT_DOTDEFAULT should not contain '.'")); + if (!def.empty()) + parse_opts(def.c_str()); + break; + } + case 'A': + opt_hide_sets_ = true; + break; + case 'c': + opt_circles_ = true; + break; + case 'C': + if (*options != '(') + throw std::runtime_error + ("invalid node color specification for print_dot()"); + { + auto* end = strchr(++options, ')'); + if (!end) + throw std::runtime_error + ("invalid node color specification for print_dot()"); + opt_node_color_ = std::string(options, end - options); + options = end + 1; + } + break; + case 'h': + opt_horizontal_ = true; + break; + case 'f': + if (*options != '(') + throw std::runtime_error + (std::string("invalid font specification for dotty()")); + { + auto* end = strchr(++options, ')'); + if (!end) + throw std::runtime_error + (std::string("invalid font specification for dotty()")); + opt_font_ = std::string(options, end - options); + options = end + 1; + } + break; + case 'v': + opt_horizontal_ = false; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'a': + case 'b': + case 'B': + case 'e': + case 'n': + case 'N': + case 'o': + case 'r': + case 'R': + case 's': + case 't': + case '+': + case '<': + case '#': + // All these options are implemented by dotty() on TGBA, + // but are not implemented here. We simply ignore them, + // because raising an exception if they are in + // SPOT_DEFAULT would be annoying. + break; + default: + throw std::runtime_error + (std::string("unknown option for dotty(): ") + c); + } } public: dotty_bfs(std::ostream& os, const const_ta_ptr& a, - const char* opt) : + const char* opt) : ta_reachable_iterator_breadth_first(a), os_(os) { - parse_opts(opt ? opt : "."); + parse_opts(opt ? opt : "."); } void @@ -145,56 +145,56 @@ namespace spot { os_ << "digraph G {\n"; - if (opt_horizontal_) - os_ << " rankdir=LR\n"; - if (opt_circles_) - os_ << " node [shape=\"circle\"]\n"; - if (!opt_node_color_.empty()) - os_ << " node [style=\"filled\", fillcolor=\"" - << opt_node_color_ << "\"]\n"; - if (!opt_font_.empty()) - os_ << " fontname=\"" << opt_font_ - << "\"\n node [fontname=\"" << opt_font_ - << "\"]\n edge [fontname=\"" << opt_font_ - << "\"]\n"; + if (opt_horizontal_) + os_ << " rankdir=LR\n"; + if (opt_circles_) + os_ << " node [shape=\"circle\"]\n"; + if (!opt_node_color_.empty()) + os_ << " node [style=\"filled\", fillcolor=\"" + << opt_node_color_ << "\"]\n"; + if (!opt_font_.empty()) + os_ << " fontname=\"" << opt_font_ + << "\"\n node [fontname=\"" << opt_font_ + << "\"]\n edge [fontname=\"" << opt_font_ + << "\"]\n"; - // Always copy the environment variable into a static string, - // so that we (1) look it up once, but (2) won't crash if the - // environment is changed. - static std::string extra = []() - { - auto s = getenv("SPOT_DOTEXTRA"); - return s ? s : ""; - }(); - // Any extra text passed in the SPOT_DOTEXTRA environment - // variable should be output at the end of the "header", so - // that our setup can be overridden. - if (!extra.empty()) - os_ << " " << extra << '\n'; + // Always copy the environment variable into a static string, + // so that we (1) look it up once, but (2) won't crash if the + // environment is changed. + static std::string extra = []() + { + auto s = getenv("SPOT_DOTEXTRA"); + return s ? s : ""; + }(); + // Any extra text passed in the SPOT_DOTEXTRA environment + // variable should be output at the end of the "header", so + // that our setup can be overridden. + if (!extra.empty()) + os_ << " " << extra << '\n'; artificial_initial_state_ = t_automata_->get_artificial_initial_state(); ta::const_states_set_t init_states_set; if (artificial_initial_state_) - { - init_states_set.insert(artificial_initial_state_); - os_ << " 0 [label=\"\", style=invis, height=0]\n 0 -> 1\n"; - } + { + init_states_set.insert(artificial_initial_state_); + os_ << " 0 [label=\"\", style=invis, height=0]\n 0 -> 1\n"; + } else - { - int n = 0; - init_states_set = t_automata_->get_initial_states_set(); - for (auto s: init_states_set) - { - bdd init_condition = t_automata_->get_state_condition(s); - std::string label = bdd_format_formula(t_automata_->get_dict(), - init_condition); - ++n; - os_ << " " << -n << " [label=\"\", style=invis, height=0]\n " - << -n << " -> " << n << " [label=\"" << label << "\"]\n"; - } - } + { + int n = 0; + init_states_set = t_automata_->get_initial_states_set(); + for (auto s: init_states_set) + { + bdd init_condition = t_automata_->get_state_condition(s); + std::string label = bdd_format_formula(t_automata_->get_dict(), + init_condition); + ++n; + os_ << " " << -n << " [label=\"\", style=invis, height=0]\n " + << -n << " -> " << n << " [label=\"" << label << "\"]\n"; + } + } } void @@ -209,41 +209,41 @@ namespace spot std::string style; if (t_automata_->is_accepting_state(s)) - style = ",peripheries=2"; + style = ",peripheries=2"; - if (t_automata_->is_livelock_accepting_state(s)) - style += ",shape=box"; + if (t_automata_->is_livelock_accepting_state(s)) + style += ",shape=box"; - os_ << " " << n << " [label="; - if (s == artificial_initial_state_) - os_ << "init"; - else - os_ << quote_unless_bare_word(t_automata_->format_state(s)); - os_ << style << "]\n"; + os_ << " " << n << " [label="; + if (s == artificial_initial_state_) + os_ << "init"; + else + os_ << quote_unless_bare_word(t_automata_->format_state(s)); + os_ << style << "]\n"; } void process_link(int in, int out, const ta_succ_iterator* si) { - bdd_dict_ptr d = t_automata_->get_dict(); - std::string label = - ((in == 1 && artificial_initial_state_) - ? bdd_format_formula(d, si->cond()) - : bdd_format_accset(d, si->cond())); + bdd_dict_ptr d = t_automata_->get_dict(); + std::string label = + ((in == 1 && artificial_initial_state_) + ? bdd_format_formula(d, si->cond()) + : bdd_format_accset(d, si->cond())); - if (label.empty()) - label = "{}"; + if (label.empty()) + label = "{}"; - if (!opt_hide_sets_) - { - label += "\n"; - label += t_automata_->acc(). - format(si->acc()); - } + if (!opt_hide_sets_) + { + label += "\n"; + label += t_automata_->acc(). + format(si->acc()); + } os_ << " " << in << " -> " << out << " [label=\""; - escape_str(os_, label); - os_ << "\"]\n"; + escape_str(os_, label); + os_ << "\"]\n"; } private: diff --git a/spot/taalgos/dot.hh b/spot/taalgos/dot.hh index 347070ff6..76e6d453f 100644 --- a/spot/taalgos/dot.hh +++ b/spot/taalgos/dot.hh @@ -26,5 +26,5 @@ namespace spot { SPOT_API std::ostream& print_dot(std::ostream& os, const const_ta_ptr& a, - const char* opt = nullptr); + const char* opt = nullptr); } diff --git a/spot/taalgos/emptinessta.cc b/spot/taalgos/emptinessta.cc index 37fb73944..952e54073 100644 --- a/spot/taalgos/emptinessta.cc +++ b/spot/taalgos/emptinessta.cc @@ -102,10 +102,10 @@ namespace spot (ta_init_it_->dst()), kripke_init_state->clone()); if (!h.emplace(init, num + 1).second) - { - init->destroy(); - continue; - } + { + init->destroy(); + continue; + } scc.push(++num); arc.push(0U); @@ -146,7 +146,7 @@ namespace spot } // fill rem with any component removed, - auto i = h.find(curr); + auto i = h.find(curr); assert(i != h.end()); scc.rem().push_front(curr); @@ -168,7 +168,7 @@ namespace spot { // removing states for (auto j: scc.rem()) - h[j] = -1; + h[j] = -1; dec_depth(scc.rem().size()); scc.pop(); assert(!arc.empty()); @@ -209,7 +209,7 @@ namespace spot // We do not need SUCC from now on. // Are we going to a new state? - auto p = h.emplace(dest, num + 1); + auto p = h.emplace(dest, num + 1); if (p.second) { // Number it, stack it, and register its successors @@ -277,23 +277,23 @@ namespace spot scc.rem().splice(scc.rem().end(), rem); bool is_accepting_sscc = scc.top().is_accepting - || a_->acc().accepting(scc.top().condition); + || a_->acc().accepting(scc.top().condition); if (is_accepting_sscc) { trace - << "PASS 1: SUCCESS: a_->is_livelock_accepting_state(curr): " - << a_->is_livelock_accepting_state(curr) << '\n'; + << "PASS 1: SUCCESS: a_->is_livelock_accepting_state(curr): " + << a_->is_livelock_accepting_state(curr) << '\n'; trace << "PASS 1: scc.top().condition : " - << scc.top().condition << '\n'; + << scc.top().condition << '\n'; trace << "PASS 1: a_->acc().all_sets() : " - << (a_->acc().all_sets()) << '\n'; + << (a_->acc().all_sets()) << '\n'; trace - << ("PASS 1 CYCLE and accepting? ") - << a_->acc().accepting(scc.top().condition) - << std::endl; + << ("PASS 1 CYCLE and accepting? ") + << a_->acc().accepting(scc.top().condition) + << std::endl; clear(h, todo, ta_init_it_); return true; } @@ -315,19 +315,19 @@ namespace spot h_livelock_root = h[livelock_roots.top()]; if (heuristic_livelock_detection(dest, h, h_livelock_root, - liveset_curr)) + liveset_curr)) { clear(h, todo, ta_init_it_); return true; } for (const state* succ: liveset_dest) - if (heuristic_livelock_detection(succ, h, h_livelock_root, - liveset_curr)) - { - clear(h, todo, ta_init_it_); - return true; - } + if (heuristic_livelock_detection(succ, h, h_livelock_root, + liveset_curr)) + { + clear(h, todo, ta_init_it_); + return true; + } } } @@ -403,11 +403,11 @@ namespace spot auto init = ta_init_it_.front(); ta_init_it_.pop(); - if (!h.emplace(init, num + 1).second) - { - init->destroy(); - continue; - } + if (!h.emplace(init, num + 1).second) + { + init->destroy(); + continue; + } sscc.push(num); sscc.top().is_accepting = t->is_livelock_accepting_state(init); @@ -435,7 +435,7 @@ namespace spot trace << "PASS 2 : backtrack\n"; // fill rem with any component removed, - auto i = h.find(curr); + auto i = h.find(curr); assert(i != h.end()); sscc.rem().push_front(curr); @@ -449,7 +449,7 @@ namespace spot { // removing states for (auto j: sscc.rem()) - h[j] = -1; + h[j] = -1; dec_depth(sscc.rem().size()); sscc.pop(); } @@ -498,10 +498,10 @@ namespace spot inc_depth(); continue; } - else - { - dest->destroy(); - } + else + { + dest->destroy(); + } // If we have reached a dead component, ignore it. if (i->second == -1) @@ -509,12 +509,12 @@ namespace spot //self loop state if (!curr->compare(i->first)) - if (t->is_livelock_accepting_state(curr)) - { - clear(h, todo, ta_init_it_); - trace << "PASS 2: SUCCESS\n"; - return true; - } + if (t->is_livelock_accepting_state(curr)) + { + clear(h, todo, ta_init_it_); + trace << "PASS 2: SUCCESS\n"; + return true; + } // Now this is the most interesting case. We have reached a // state S1 which is already part of a non-dead SSCC. Any such diff --git a/spot/taalgos/emptinessta.hh b/spot/taalgos/emptinessta.hh index 32c219141..39cc65106 100644 --- a/spot/taalgos/emptinessta.hh +++ b/spot/taalgos/emptinessta.hh @@ -34,7 +34,7 @@ namespace spot namespace { typedef std::pair pair_state_iter; + ta_succ_iterator_product*> pair_state_iter; } /// \addtogroup ta_emptiness_check Emptiness-checks @@ -111,7 +111,7 @@ namespace spot /// this heuristic is described in the paper cited above bool check(bool disable_second_pass = false, - bool disable_heuristic_for_livelock_detection = false); + bool disable_heuristic_for_livelock_detection = false); /// \brief Check whether the product automaton contains /// a livelock-accepting run diff --git a/spot/taalgos/minimize.cc b/spot/taalgos/minimize.cc index 2c086c77b..fee3fffd7 100644 --- a/spot/taalgos/minimize.cc +++ b/spot/taalgos/minimize.cc @@ -47,8 +47,8 @@ namespace spot { static std::ostream& dump_hash_set(const hash_set* hs, - const const_ta_ptr& aut, - std::ostream& out) + const const_ta_ptr& aut, + std::ostream& out) { out << '{'; const char* sep = ""; @@ -73,7 +73,7 @@ namespace spot // automaton static void build_result(const const_ta_ptr& a, std::list& sets, - twa_graph_ptr result_tgba, const ta_explicit_ptr& result) + twa_graph_ptr result_tgba, const ta_explicit_ptr& result) { // For each set, create a state in the tgbaulting automaton. // For a state s, state_num[s] is the number of the state in the minimal @@ -82,103 +82,103 @@ namespace spot std::list::iterator sit; unsigned num = 0; for (sit = sets.begin(); sit != sets.end(); ++sit) - { - hash_set::iterator hit; - hash_set* h = *sit; - for (hit = h->begin(); hit != h->end(); ++hit) - state_num[*hit] = num; - result_tgba->new_state(); - ++num; - } + { + hash_set::iterator hit; + hash_set* h = *sit; + for (hit = h->begin(); hit != h->end(); ++hit) + state_num[*hit] = num; + result_tgba->new_state(); + ++num; + } // For each transition in the initial automaton, add the corresponding // transition in ta. for (sit = sets.begin(); sit != sets.end(); ++sit) - { - hash_set::iterator hit; - hash_set* h = *sit; - hit = h->begin(); - const state* src = *hit; - unsigned src_num = state_num[src]; + { + hash_set::iterator hit; + hash_set* h = *sit; + hit = h->begin(); + const state* src = *hit; + unsigned src_num = state_num[src]; - bdd tgba_condition = bddtrue; - bool is_initial_state = a->is_initial_state(src); - if (!a->get_artificial_initial_state() && is_initial_state) - tgba_condition = a->get_state_condition(src); - bool is_accepting_state = a->is_accepting_state(src); - bool is_livelock_accepting_state = - a->is_livelock_accepting_state(src); + bdd tgba_condition = bddtrue; + bool is_initial_state = a->is_initial_state(src); + if (!a->get_artificial_initial_state() && is_initial_state) + tgba_condition = a->get_state_condition(src); + bool is_accepting_state = a->is_accepting_state(src); + bool is_livelock_accepting_state = + a->is_livelock_accepting_state(src); - state_ta_explicit* new_src = - new state_ta_explicit(result_tgba->state_from_number(src_num), - tgba_condition, is_initial_state, - is_accepting_state, - is_livelock_accepting_state); + state_ta_explicit* new_src = + new state_ta_explicit(result_tgba->state_from_number(src_num), + tgba_condition, is_initial_state, + is_accepting_state, + is_livelock_accepting_state); - state_ta_explicit* ta_src = result->add_state(new_src); + state_ta_explicit* ta_src = result->add_state(new_src); - if (ta_src != new_src) - { - delete new_src; - } - else if (a->get_artificial_initial_state()) - { - if (a->get_artificial_initial_state() == src) - result->set_artificial_initial_state(new_src); - } - else if (is_initial_state) - { - result->add_to_initial_states_set(new_src); - } + if (ta_src != new_src) + { + delete new_src; + } + else if (a->get_artificial_initial_state()) + { + if (a->get_artificial_initial_state() == src) + result->set_artificial_initial_state(new_src); + } + else if (is_initial_state) + { + result->add_to_initial_states_set(new_src); + } - ta_succ_iterator* succit = a->succ_iter(src); + ta_succ_iterator* succit = a->succ_iter(src); - for (succit->first(); !succit->done(); succit->next()) - { - const state* dst = succit->dst(); - hash_map::const_iterator i = state_num.find(dst); + for (succit->first(); !succit->done(); succit->next()) + { + const state* dst = succit->dst(); + hash_map::const_iterator i = state_num.find(dst); - if (i == state_num.end()) // Ignore useless destinations. - continue; + if (i == state_num.end()) // Ignore useless destinations. + continue; - bdd tgba_condition = bddtrue; - is_initial_state = a->is_initial_state(dst); - if (!a->get_artificial_initial_state() && is_initial_state) - tgba_condition = a->get_state_condition(dst); - bool is_accepting_state = a->is_accepting_state(dst); - bool is_livelock_accepting_state = - a->is_livelock_accepting_state(dst); + bdd tgba_condition = bddtrue; + is_initial_state = a->is_initial_state(dst); + if (!a->get_artificial_initial_state() && is_initial_state) + tgba_condition = a->get_state_condition(dst); + bool is_accepting_state = a->is_accepting_state(dst); + bool is_livelock_accepting_state = + a->is_livelock_accepting_state(dst); - state_ta_explicit* new_dst = - new state_ta_explicit - (result_tgba->state_from_number(i->second), - tgba_condition, is_initial_state, - is_accepting_state, - is_livelock_accepting_state); + state_ta_explicit* new_dst = + new state_ta_explicit + (result_tgba->state_from_number(i->second), + tgba_condition, is_initial_state, + is_accepting_state, + is_livelock_accepting_state); - state_ta_explicit* ta_dst = result->add_state(new_dst); + state_ta_explicit* ta_dst = result->add_state(new_dst); - if (ta_dst != new_dst) - { - delete new_dst; - } - else if (a->get_artificial_initial_state()) - { - if (a->get_artificial_initial_state() == dst) - result->set_artificial_initial_state(new_dst); - } + if (ta_dst != new_dst) + { + delete new_dst; + } + else if (a->get_artificial_initial_state()) + { + if (a->get_artificial_initial_state() == dst) + result->set_artificial_initial_state(new_dst); + } - else if (is_initial_state) - result->add_to_initial_states_set(new_dst); + else if (is_initial_state) + result->add_to_initial_states_set(new_dst); - result->create_transition - (ta_src, succit->cond(), - succit->acc(), - ta_dst); - } - delete succit; - } + result->create_transition + (ta_src, succit->cond(), + succit->acc(), + ta_dst); + } + delete succit; + } } static partition_t @@ -187,22 +187,22 @@ namespace spot unsigned num_sets = ta_->acc().num_sets(); std::map m2b; int acc_vars = ta_->get_dict()->register_anonymous_variables(num_sets, - &m2b); + &m2b); auto mark_to_bdd = [&](acc_cond::mark_t m) -> bdd - { - auto i = m2b.find(m); - if (i != m2b.end()) - return i->second; + { + auto i = m2b.find(m); + if (i != m2b.end()) + return i->second; - bdd res = bddtrue; - for (unsigned n = 0; n < num_sets; ++n) - if (m.has(n)) - res &= bdd_ithvar(acc_vars + n); - else - res &= bdd_nithvar(acc_vars + n); - m2b.emplace_hint(i, m, res); - return res; - }; + bdd res = bddtrue; + for (unsigned n = 0; n < num_sets; ++n) + if (m.has(n)) + res &= bdd_ithvar(acc_vars + n); + else + res &= bdd_nithvar(acc_vars + n); + m2b.emplace_hint(i, m, res); + return res; + }; partition_t cur_run; partition_t next_run; @@ -231,22 +231,22 @@ namespace spot auto artificial_initial_state = ta_->get_artificial_initial_state(); for (it = states_set.begin(); it != states_set.end(); ++it) - { - const state* s = *it; - if (s == artificial_initial_state) - I->insert(s); - else if (!artificial_initial_state && ta_->is_initial_state(s)) - I->insert(s); - else if (ta_->is_livelock_accepting_state(s) - && ta_->is_accepting_state(s)) - G_F->insert(s); - else if (ta_->is_accepting_state(s)) - F->insert(s); - else if (ta_->is_livelock_accepting_state(s)) - G->insert(s); - else - S->insert(s); - } + { + const state* s = *it; + if (s == artificial_initial_state) + I->insert(s); + else if (!artificial_initial_state && ta_->is_initial_state(s)) + I->insert(s); + else if (ta_->is_livelock_accepting_state(s) + && ta_->is_accepting_state(s)) + G_F->insert(s); + else if (ta_->is_accepting_state(s)) + F->insert(s); + else if (ta_->is_livelock_accepting_state(s)) + G->insert(s); + else + S->insert(s); + } hash_map state_set_map; @@ -255,103 +255,103 @@ namespace spot // Use bdd variables to number sets. set_num is the first variable // available. unsigned set_num = - ta_->get_dict()->register_anonymous_variables(size, &m2b); + ta_->get_dict()->register_anonymous_variables(size, &m2b); std::set free_var; for (unsigned i = set_num; i < set_num + size; ++i) - free_var.insert(i); + free_var.insert(i); std::map used_var; for (hash_set::const_iterator i = I->begin(); i != I->end(); ++i) - { - hash_set* cI = new hash_set; - cI->insert(*i); - done.push_back(cI); + { + hash_set* cI = new hash_set; + cI->insert(*i); + done.push_back(cI); - used_var[set_num] = 1; - free_var.erase(set_num); - state_set_map[*i] = set_num; - ++set_num; + used_var[set_num] = 1; + free_var.erase(set_num); + state_set_map[*i] = set_num; + ++set_num; - } + } delete I; if (!G->empty()) - { - unsigned s = G->size(); - unsigned num = set_num; - ++set_num; - used_var[num] = s; - free_var.erase(num); - if (s > 1) - cur_run.push_back(G); - else - done.push_back(G); - for (hash_set::const_iterator i = G->begin(); i != G->end(); ++i) - state_set_map[*i] = num; + { + unsigned s = G->size(); + unsigned num = set_num; + ++set_num; + used_var[num] = s; + free_var.erase(num); + if (s > 1) + cur_run.push_back(G); + else + done.push_back(G); + for (hash_set::const_iterator i = G->begin(); i != G->end(); ++i) + state_set_map[*i] = num; - } + } else - { - delete G; - } + { + delete G; + } if (!F->empty()) - { - unsigned s = F->size(); - unsigned num = set_num; - ++set_num; - used_var[num] = s; - free_var.erase(num); - if (s > 1) - cur_run.push_back(F); - else - done.push_back(F); - for (hash_set::const_iterator i = F->begin(); i != F->end(); ++i) - state_set_map[*i] = num; - } + { + unsigned s = F->size(); + unsigned num = set_num; + ++set_num; + used_var[num] = s; + free_var.erase(num); + if (s > 1) + cur_run.push_back(F); + else + done.push_back(F); + for (hash_set::const_iterator i = F->begin(); i != F->end(); ++i) + state_set_map[*i] = num; + } else - { - delete F; - } + { + delete F; + } if (!G_F->empty()) - { - unsigned s = G_F->size(); - unsigned num = set_num; - ++set_num; - used_var[num] = s; - free_var.erase(num); - if (s > 1) - cur_run.push_back(G_F); - else - done.push_back(G_F); - for (hash_set::const_iterator i = G_F->begin(); i != G_F->end(); ++i) - state_set_map[*i] = num; - } + { + unsigned s = G_F->size(); + unsigned num = set_num; + ++set_num; + used_var[num] = s; + free_var.erase(num); + if (s > 1) + cur_run.push_back(G_F); + else + done.push_back(G_F); + for (hash_set::const_iterator i = G_F->begin(); i != G_F->end(); ++i) + state_set_map[*i] = num; + } else - { - delete G_F; - } + { + delete G_F; + } if (!S->empty()) - { - unsigned s = S->size(); - unsigned num = set_num; - ++set_num; - used_var[num] = s; - free_var.erase(num); - if (s > 1) - cur_run.push_back(S); - else - done.push_back(S); - for (hash_set::const_iterator i = S->begin(); i != S->end(); ++i) - state_set_map[*i] = num; - } + { + unsigned s = S->size(); + unsigned num = set_num; + ++set_num; + used_var[num] = s; + free_var.erase(num); + if (s > 1) + cur_run.push_back(S); + else + done.push_back(S); + for (hash_set::const_iterator i = S->begin(); i != S->end(); ++i) + state_set_map[*i] = num; + } else - { - delete S; - } + { + delete S; + } // A bdd_states_map is a list of formulae (in a BDD form) @@ -366,132 +366,132 @@ namespace spot bdd bdd_false_acceptance_condition = bdd_ithvar(num); while (did_split) - { - did_split = false; - while (!cur_run.empty()) - { - // Get a set to process. - hash_set* cur = cur_run.front(); - cur_run.pop_front(); + { + did_split = false; + while (!cur_run.empty()) + { + // Get a set to process. + hash_set* cur = cur_run.front(); + cur_run.pop_front(); - trace - << "processing " << format_hash_set(cur, ta_) << std::endl; + trace + << "processing " << format_hash_set(cur, ta_) << std::endl; - hash_set::iterator hi; - bdd_states_map bdd_map; - for (hi = cur->begin(); hi != cur->end(); ++hi) - { - const state* src = *hi; - bdd f = bddfalse; - ta_succ_iterator* si = ta_->succ_iter(src); - trace << "+src: " << src << std::endl; - for (si->first(); !si->done(); si->next()) - { - const state* dst = si->dst(); - hash_map::const_iterator i = state_set_map.find(dst); + hash_set::iterator hi; + bdd_states_map bdd_map; + for (hi = cur->begin(); hi != cur->end(); ++hi) + { + const state* src = *hi; + bdd f = bddfalse; + ta_succ_iterator* si = ta_->succ_iter(src); + trace << "+src: " << src << std::endl; + for (si->first(); !si->done(); si->next()) + { + const state* dst = si->dst(); + hash_map::const_iterator i = state_set_map.find(dst); - assert(i != state_set_map.end()); - auto curacc = - mark_to_bdd(si->acc()); - f |= (bdd_ithvar(i->second) - & si->cond() & curacc); - trace - << "+f: " << bdd_format_accset(ta_->get_dict(), f) - << "\n -bdd_ithvar(i->second): " - << bdd_format_accset(ta_->get_dict(), - bdd_ithvar(i->second)) - << "\n -si->cond(): " - << bdd_format_accset(ta_->get_dict(), - si->cond()) - << "\n -current_acceptance_conditions: " - << si->acc() - << std::endl; - } - delete si; + assert(i != state_set_map.end()); + auto curacc = + mark_to_bdd(si->acc()); + f |= (bdd_ithvar(i->second) + & si->cond() & curacc); + trace + << "+f: " << bdd_format_accset(ta_->get_dict(), f) + << "\n -bdd_ithvar(i->second): " + << bdd_format_accset(ta_->get_dict(), + bdd_ithvar(i->second)) + << "\n -si->cond(): " + << bdd_format_accset(ta_->get_dict(), + si->cond()) + << "\n -current_acceptance_conditions: " + << si->acc() + << std::endl; + } + delete si; - // Have we already seen this formula ? - bdd_states_map::iterator bsi = bdd_map.find(f); - if (bsi == bdd_map.end()) - { - // No, create a new set. - hash_set* new_set = new hash_set; - new_set->insert(src); - bdd_map[f] = new_set; - } - else - { - // Yes, add the current state to the set. - bsi->second->insert(src); - } - } + // Have we already seen this formula ? + bdd_states_map::iterator bsi = bdd_map.find(f); + if (bsi == bdd_map.end()) + { + // No, create a new set. + hash_set* new_set = new hash_set; + new_set->insert(src); + bdd_map[f] = new_set; + } + else + { + // Yes, add the current state to the set. + bsi->second->insert(src); + } + } - bdd_states_map::iterator bsi = bdd_map.begin(); - if (bdd_map.size() == 1) - { - // The set was not split. - trace - << "set " << format_hash_set(bsi->second, ta_) - << " was not split" << std::endl; - next_run.push_back(bsi->second); - } - else - { - did_split = true; - for (; bsi != bdd_map.end(); ++bsi) - { - hash_set* set = bsi->second; - // Free the number associated to these states. - unsigned num = state_set_map[*set->begin()]; - assert(used_var.find(num) != used_var.end()); - unsigned left = (used_var[num] -= set->size()); - // Make sure LEFT does not become negative - // (hence bigger than SIZE when read as unsigned) - assert(left < size); - if (left == 0) - { - used_var.erase(num); - free_var.insert(num); - } - // Pick a free number - assert(!free_var.empty()); - num = *free_var.begin(); - free_var.erase(free_var.begin()); - used_var[num] = set->size(); - for (hash_set::iterator hit = set->begin(); - hit != set->end(); ++hit) - state_set_map[*hit] = num; - // Trivial sets can't be splitted any further. - if (set->size() == 1) - { - trace - << "set " << format_hash_set(set, ta_) - << " is minimal" << std::endl; - done.push_back(set); - } - else - { - trace - << "set " << format_hash_set(set, ta_) - << " should be processed further" << std::endl; - next_run.push_back(set); - } - } - } - delete cur; - } - if (did_split) - trace - << "splitting did occur during this pass." << std::endl; + bdd_states_map::iterator bsi = bdd_map.begin(); + if (bdd_map.size() == 1) + { + // The set was not split. + trace + << "set " << format_hash_set(bsi->second, ta_) + << " was not split" << std::endl; + next_run.push_back(bsi->second); + } + else + { + did_split = true; + for (; bsi != bdd_map.end(); ++bsi) + { + hash_set* set = bsi->second; + // Free the number associated to these states. + unsigned num = state_set_map[*set->begin()]; + assert(used_var.find(num) != used_var.end()); + unsigned left = (used_var[num] -= set->size()); + // Make sure LEFT does not become negative + // (hence bigger than SIZE when read as unsigned) + assert(left < size); + if (left == 0) + { + used_var.erase(num); + free_var.insert(num); + } + // Pick a free number + assert(!free_var.empty()); + num = *free_var.begin(); + free_var.erase(free_var.begin()); + used_var[num] = set->size(); + for (hash_set::iterator hit = set->begin(); + hit != set->end(); ++hit) + state_set_map[*hit] = num; + // Trivial sets can't be splitted any further. + if (set->size() == 1) + { + trace + << "set " << format_hash_set(set, ta_) + << " is minimal" << std::endl; + done.push_back(set); + } + else + { + trace + << "set " << format_hash_set(set, ta_) + << " should be processed further" << std::endl; + next_run.push_back(set); + } + } + } + delete cur; + } + if (did_split) + trace + << "splitting did occur during this pass." << std::endl; - std::swap(cur_run, next_run); - } + std::swap(cur_run, next_run); + } done.splice(done.end(), cur_run); #ifdef TRACE trace << "Final partition: "; for (partition_t::const_iterator i = done.begin(); i != done.end(); ++i) - trace << format_hash_set(*i, ta_) << ' '; + trace << format_hash_set(*i, ta_) << ' '; trace << std::endl; #endif diff --git a/spot/taalgos/tgba2ta.cc b/spot/taalgos/tgba2ta.cc index 48d30fb14..5355c3cc3 100644 --- a/spot/taalgos/tgba2ta.cc +++ b/spot/taalgos/tgba2ta.cc @@ -51,17 +51,17 @@ namespace spot { if (artificial_livelock_acc_state) - { - auto artificial_livelock_acc_state_added = + { + auto artificial_livelock_acc_state_added = testing_automata->add_state(artificial_livelock_acc_state); - // unique artificial_livelock_acc_state - assert(artificial_livelock_acc_state_added - == artificial_livelock_acc_state); - (void)artificial_livelock_acc_state_added; - artificial_livelock_acc_state->set_livelock_accepting_state(true); - artificial_livelock_acc_state->free_transitions(); - } + // unique artificial_livelock_acc_state + assert(artificial_livelock_acc_state_added + == artificial_livelock_acc_state); + (void)artificial_livelock_acc_state_added; + artificial_livelock_acc_state->set_livelock_accepting_state(true); + artificial_livelock_acc_state->free_transitions(); + } ta::states_set_t states_set = testing_automata->get_states_set(); ta::states_set_t::iterator it; @@ -70,86 +70,86 @@ namespace spot new state_ta_explicit::transitions; for (it = states_set.begin(); it != states_set.end(); ++it) - { - auto source = const_cast - (static_cast(*it)); + { + auto source = const_cast + (static_cast(*it)); - transitions_to_livelock_states->clear(); + transitions_to_livelock_states->clear(); - state_ta_explicit::transitions* trans = source->get_transitions(); - state_ta_explicit::transitions::iterator it_trans; + state_ta_explicit::transitions* trans = source->get_transitions(); + state_ta_explicit::transitions::iterator it_trans; - if (trans) - for (it_trans = trans->begin(); it_trans != trans->end();) - { - auto dest = const_cast((*it_trans)->dest); + if (trans) + for (it_trans = trans->begin(); it_trans != trans->end();) + { + auto dest = const_cast((*it_trans)->dest); - state_ta_explicit::transitions* dest_trans = - dest->get_transitions(); - bool dest_trans_empty = !dest_trans || dest_trans->empty(); + state_ta_explicit::transitions* dest_trans = + dest->get_transitions(); + bool dest_trans_empty = !dest_trans || dest_trans->empty(); - //select transitions where a destination is a livelock state - // which isn't a Buchi accepting state and has successors - if (dest->is_livelock_accepting_state() - && (!dest->is_accepting_state()) && (!dest_trans_empty)) - transitions_to_livelock_states->push_front(*it_trans); + //select transitions where a destination is a livelock state + // which isn't a Buchi accepting state and has successors + if (dest->is_livelock_accepting_state() + && (!dest->is_accepting_state()) && (!dest_trans_empty)) + transitions_to_livelock_states->push_front(*it_trans); - // optimization to have, after minimization, an unique - // livelock state which has no successors - if (dest->is_livelock_accepting_state() && (dest_trans_empty)) - dest->set_accepting_state(false); + // optimization to have, after minimization, an unique + // livelock state which has no successors + if (dest->is_livelock_accepting_state() && (dest_trans_empty)) + dest->set_accepting_state(false); - ++it_trans; - } + ++it_trans; + } - if (transitions_to_livelock_states) - { - state_ta_explicit::transitions::iterator it_trans; + if (transitions_to_livelock_states) + { + state_ta_explicit::transitions::iterator it_trans; - for (it_trans = transitions_to_livelock_states->begin(); - it_trans != transitions_to_livelock_states->end(); - ++it_trans) - { - if (artificial_livelock_acc_state) - { - testing_automata->create_transition - (source, - (*it_trans)->condition, - (*it_trans)->acceptance_conditions, - artificial_livelock_acc_state, true); - } - else - { - testing_automata->create_transition - (source, - (*it_trans)->condition, - (*it_trans)->acceptance_conditions, - ((*it_trans)->dest)->stuttering_reachable_livelock, - true); - } - } - } - } + for (it_trans = transitions_to_livelock_states->begin(); + it_trans != transitions_to_livelock_states->end(); + ++it_trans) + { + if (artificial_livelock_acc_state) + { + testing_automata->create_transition + (source, + (*it_trans)->condition, + (*it_trans)->acceptance_conditions, + artificial_livelock_acc_state, true); + } + else + { + testing_automata->create_transition + (source, + (*it_trans)->condition, + (*it_trans)->acceptance_conditions, + ((*it_trans)->dest)->stuttering_reachable_livelock, + true); + } + } + } + } delete transitions_to_livelock_states; for (it = states_set.begin(); it != states_set.end(); ++it) - { - state_ta_explicit* state = static_cast (*it); - state_ta_explicit::transitions* state_trans = + { + state_ta_explicit* state = static_cast (*it); + state_ta_explicit::transitions* state_trans = (state)->get_transitions(); - bool state_trans_empty = !state_trans || state_trans->empty(); + bool state_trans_empty = !state_trans || state_trans->empty(); - if (state->is_livelock_accepting_state() - && (!state->is_accepting_state()) && (!state_trans_empty)) - state->set_livelock_accepting_state(false); - } + if (state->is_livelock_accepting_state() + && (!state->is_accepting_state()) && (!state_trans_empty)) + state->set_livelock_accepting_state(false); + } } static void compute_livelock_acceptance_states(const ta_explicit_ptr& testing_aut, - bool single_pass_emptiness_check, - state_ta_explicit* - artificial_livelock_acc_state) + bool single_pass_emptiness_check, + state_ta_explicit* + artificial_livelock_acc_state) { // We use five main data in this algorithm: // * sscc: a stack of strongly stuttering-connected components (SSCC) @@ -177,234 +177,234 @@ namespace spot std::stack init_set; for (auto s: testing_aut->get_initial_states_set()) - init_set.push(s); + init_set.push(s); while (!init_set.empty()) - { - // Setup depth-first search from initial states. + { + // Setup depth-first search from initial states. - { - auto init = down_cast (init_set.top()); - init_set.pop(); + { + auto init = down_cast (init_set.top()); + init_set.pop(); - if (!h.emplace(init, num + 1).second) - { - init->destroy(); - continue; - } + if (!h.emplace(init, num + 1).second) + { + init->destroy(); + continue; + } - sscc.push(++num); - arc.push(0U); - sscc.top().is_accepting + sscc.push(++num); + arc.push(0U); + sscc.top().is_accepting = testing_aut->is_accepting_state(init); - twa_succ_iterator* iter = testing_aut->succ_iter(init); - iter->first(); - todo.emplace(init, iter); - } + twa_succ_iterator* iter = testing_aut->succ_iter(init); + iter->first(); + todo.emplace(init, iter); + } - while (!todo.empty()) - { - auto curr = todo.top().first; + while (!todo.empty()) + { + auto curr = todo.top().first; - auto i = h.find(curr); - // If we have reached a dead component, ignore it. - if (i != h.end() && i->second == -1) - { - todo.pop(); - continue; - } + auto i = h.find(curr); + // If we have reached a dead component, ignore it. + if (i != h.end() && i->second == -1) + { + todo.pop(); + continue; + } - // We are looking at the next successor in SUCC. - twa_succ_iterator* succ = todo.top().second; + // We are looking at the next successor in SUCC. + twa_succ_iterator* succ = todo.top().second; - // If there is no more successor, backtrack. - if (succ->done()) - { - // We have explored all successors of state CURR. + // If there is no more successor, backtrack. + if (succ->done()) + { + // We have explored all successors of state CURR. - // Backtrack TODO. - todo.pop(); + // Backtrack TODO. + todo.pop(); - // fill rem with any component removed, - assert(i != h.end()); - sscc.rem().push_front(curr); + // fill rem with any component removed, + assert(i != h.end()); + sscc.rem().push_front(curr); - // When backtracking the root of an SSCC, we must also - // remove that SSCC from the ROOT stacks. We must - // discard from H all reachable states from this SSCC. - assert(!sscc.empty()); - if (sscc.top().index == i->second) - { - // removing states - bool is_livelock_accepting_sscc = (sscc.rem().size() > 1) - && ((sscc.top().is_accepting) || - (testing_aut->acc(). - accepting(sscc.top().condition))); - trace << "*** sscc.size() = ***" << sscc.size() << '\n'; - for (auto j: sscc.rem()) - { - h[j] = -1; + // When backtracking the root of an SSCC, we must also + // remove that SSCC from the ROOT stacks. We must + // discard from H all reachable states from this SSCC. + assert(!sscc.empty()); + if (sscc.top().index == i->second) + { + // removing states + bool is_livelock_accepting_sscc = (sscc.rem().size() > 1) + && ((sscc.top().is_accepting) || + (testing_aut->acc(). + accepting(sscc.top().condition))); + trace << "*** sscc.size() = ***" << sscc.size() << '\n'; + for (auto j: sscc.rem()) + { + h[j] = -1; - if (is_livelock_accepting_sscc) - { - // if it is an accepting sscc add the state to - // G (=the livelock-accepting states set) - trace << "*** sscc.size() > 1: states: ***" - << testing_aut->format_state(j) - << '\n'; - auto livelock_accepting_state = - const_cast - (down_cast(j)); + if (is_livelock_accepting_sscc) + { + // if it is an accepting sscc add the state to + // G (=the livelock-accepting states set) + trace << "*** sscc.size() > 1: states: ***" + << testing_aut->format_state(j) + << '\n'; + auto livelock_accepting_state = + const_cast + (down_cast(j)); - livelock_accepting_state-> - set_livelock_accepting_state(true); + livelock_accepting_state-> + set_livelock_accepting_state(true); - if (single_pass_emptiness_check) - { - livelock_accepting_state - ->set_accepting_state(true); - livelock_accepting_state - ->stuttering_reachable_livelock - = livelock_accepting_state; - } - } - } + if (single_pass_emptiness_check) + { + livelock_accepting_state + ->set_accepting_state(true); + livelock_accepting_state + ->stuttering_reachable_livelock + = livelock_accepting_state; + } + } + } - assert(!arc.empty()); - sscc.pop(); - arc.pop(); - } + assert(!arc.empty()); + sscc.pop(); + arc.pop(); + } - // automata reduction - testing_aut->delete_stuttering_and_hole_successors(curr); + // automata reduction + testing_aut->delete_stuttering_and_hole_successors(curr); - delete succ; - // Do not delete CURR: it is a key in H. - continue; - } + delete succ; + // Do not delete CURR: it is a key in H. + continue; + } - // Fetch the values destination state we are interested in... - auto dest = succ->dst(); + // Fetch the values destination state we are interested in... + auto dest = succ->dst(); - auto acc_cond = succ->acc(); - // ... and point the iterator to the next successor, for - // the next iteration. - succ->next(); - // We do not need SUCC from now on. + auto acc_cond = succ->acc(); + // ... and point the iterator to the next successor, for + // the next iteration. + succ->next(); + // We do not need SUCC from now on. - // Are we going to a new state through a stuttering transition? - bool is_stuttering_transition = - testing_aut->get_state_condition(curr) - == testing_aut->get_state_condition(dest); - auto id = h.find(dest); + // Are we going to a new state through a stuttering transition? + bool is_stuttering_transition = + testing_aut->get_state_condition(curr) + == testing_aut->get_state_condition(dest); + auto id = h.find(dest); - // Is this a new state? - if (id == h.end()) - { - if (!is_stuttering_transition) - { - init_set.push(dest); - dest->destroy(); - continue; - } + // Is this a new state? + if (id == h.end()) + { + if (!is_stuttering_transition) + { + init_set.push(dest); + dest->destroy(); + continue; + } - // Number it, stack it, and register its successors - // for later processing. - h[dest] = ++num; - sscc.push(num); - arc.push(acc_cond); - sscc.top().is_accepting = - testing_aut->is_accepting_state(dest); + // Number it, stack it, and register its successors + // for later processing. + h[dest] = ++num; + sscc.push(num); + arc.push(acc_cond); + sscc.top().is_accepting = + testing_aut->is_accepting_state(dest); - twa_succ_iterator* iter = testing_aut->succ_iter(dest); - iter->first(); - todo.emplace(dest, iter); - continue; - } - dest->destroy(); + twa_succ_iterator* iter = testing_aut->succ_iter(dest); + iter->first(); + todo.emplace(dest, iter); + continue; + } + dest->destroy(); - // If we have reached a dead component, ignore it. - if (id->second == -1) - continue; + // If we have reached a dead component, ignore it. + if (id->second == -1) + continue; - trace << "***compute_livelock_acceptance_states: CYCLE***\n"; + trace << "***compute_livelock_acceptance_states: CYCLE***\n"; - if (!curr->compare(id->first)) - { - auto self_loop_state = const_cast - (down_cast(curr)); - assert(self_loop_state); + if (!curr->compare(id->first)) + { + auto self_loop_state = const_cast + (down_cast(curr)); + assert(self_loop_state); - if (testing_aut->is_accepting_state(self_loop_state) - || (testing_aut->acc().accepting(acc_cond))) - { - self_loop_state->set_livelock_accepting_state(true); - if (single_pass_emptiness_check) - { - self_loop_state->set_accepting_state(true); - self_loop_state->stuttering_reachable_livelock - = self_loop_state; - } - } + if (testing_aut->is_accepting_state(self_loop_state) + || (testing_aut->acc().accepting(acc_cond))) + { + self_loop_state->set_livelock_accepting_state(true); + if (single_pass_emptiness_check) + { + self_loop_state->set_accepting_state(true); + self_loop_state->stuttering_reachable_livelock + = self_loop_state; + } + } - trace - << "***compute_livelock_acceptance_states: CYCLE: " - << "self_loop_state***\n"; - } + trace + << "***compute_livelock_acceptance_states: CYCLE: " + << "self_loop_state***\n"; + } - // Now this is the most interesting case. We have reached a - // state S1 which is already part of a non-dead SSCC. Any such - // non-dead SSCC has necessarily been crossed by our path to - // this state: there is a state S2 in our path which belongs - // to this SSCC too. We are going to merge all states between - // this S1 and S2 into this SSCC. - // - // This merge is easy to do because the order of the SSCC in - // ROOT is ascending: we just have to merge all SSCCs from the - // top of ROOT that have an index greater to the one of - // the SSCC of S2 (called the "threshold"). - int threshold = id->second; - std::list rem; - bool acc = false; + // Now this is the most interesting case. We have reached a + // state S1 which is already part of a non-dead SSCC. Any such + // non-dead SSCC has necessarily been crossed by our path to + // this state: there is a state S2 in our path which belongs + // to this SSCC too. We are going to merge all states between + // this S1 and S2 into this SSCC. + // + // This merge is easy to do because the order of the SSCC in + // ROOT is ascending: we just have to merge all SSCCs from the + // top of ROOT that have an index greater to the one of + // the SSCC of S2 (called the "threshold"). + int threshold = id->second; + std::list rem; + bool acc = false; - while (threshold < sscc.top().index) - { - assert(!sscc.empty()); - assert(!arc.empty()); - acc |= sscc.top().is_accepting; - acc_cond |= sscc.top().condition; - acc_cond |= arc.top(); - rem.splice(rem.end(), sscc.rem()); - sscc.pop(); - arc.pop(); - } + while (threshold < sscc.top().index) + { + assert(!sscc.empty()); + assert(!arc.empty()); + acc |= sscc.top().is_accepting; + acc_cond |= sscc.top().condition; + acc_cond |= arc.top(); + rem.splice(rem.end(), sscc.rem()); + sscc.pop(); + arc.pop(); + } - // Note that we do not always have - // threshold == sscc.top().index - // after this loop, the SSCC whose index is threshold might have - // been merged with a lower SSCC. + // Note that we do not always have + // threshold == sscc.top().index + // after this loop, the SSCC whose index is threshold might have + // been merged with a lower SSCC. - // Accumulate all acceptance conditions into the merged SSCC. - sscc.top().is_accepting |= acc; - sscc.top().condition |= acc_cond; + // Accumulate all acceptance conditions into the merged SSCC. + sscc.top().is_accepting |= acc; + sscc.top().condition |= acc_cond; - sscc.rem().splice(sscc.rem().end(), rem); + sscc.rem().splice(sscc.rem().end(), rem); - } + } - } + } if (artificial_livelock_acc_state || single_pass_emptiness_check) - transform_to_single_pass_automaton(testing_aut, - artificial_livelock_acc_state); + transform_to_single_pass_automaton(testing_aut, + artificial_livelock_acc_state); } ta_explicit_ptr build_ta(const ta_explicit_ptr& ta, bdd atomic_propositions_set_, - bool degeneralized, - bool single_pass_emptiness_check, - bool artificial_livelock_state_mode, - bool no_livelock) + bool degeneralized, + bool single_pass_emptiness_check, + bool artificial_livelock_state_mode, + bool no_livelock) { std::stack todo; @@ -414,140 +414,140 @@ namespace spot auto tgba_init_state = tgba_->get_init_state(); bdd tgba_condition = [&]() - { - bdd cond = bddfalse; - for (auto i: tgba_->succ(tgba_init_state)) - cond |= i->cond(); - return cond; - }(); + { + bdd cond = bddfalse; + for (auto i: tgba_->succ(tgba_init_state)) + cond |= i->cond(); + return cond; + }(); bool is_acc = false; if (degeneralized) - { - twa_succ_iterator* it = tgba_->succ_iter(tgba_init_state); - it->first(); - if (!it->done()) - is_acc = it->acc() != 0U; - delete it; - } + { + twa_succ_iterator* it = tgba_->succ_iter(tgba_init_state); + it->first(); + if (!it->done()) + is_acc = it->acc() != 0U; + delete it; + } bdd satone_tgba_condition; while ((satone_tgba_condition = bdd_satoneset(tgba_condition, - atomic_propositions_set_, - bddtrue)) != bddfalse) - { - tgba_condition -= satone_tgba_condition; - state_ta_explicit* init_state = new - state_ta_explicit(tgba_init_state->clone(), - satone_tgba_condition, true, is_acc); - state_ta_explicit* s = ta->add_state(init_state); - assert(s == init_state); - ta->add_to_initial_states_set(s); + atomic_propositions_set_, + bddtrue)) != bddfalse) + { + tgba_condition -= satone_tgba_condition; + state_ta_explicit* init_state = new + state_ta_explicit(tgba_init_state->clone(), + satone_tgba_condition, true, is_acc); + state_ta_explicit* s = ta->add_state(init_state); + assert(s == init_state); + ta->add_to_initial_states_set(s); - todo.push(init_state); - } + todo.push(init_state); + } tgba_init_state->destroy(); while (!todo.empty()) - { - state_ta_explicit* source = todo.top(); - todo.pop(); + { + state_ta_explicit* source = todo.top(); + todo.pop(); - twa_succ_iterator* twa_succ_it = - tgba_->succ_iter(source->get_tgba_state()); - for (twa_succ_it->first(); !twa_succ_it->done(); - twa_succ_it->next()) - { - const state* tgba_state = twa_succ_it->dst(); - bdd tgba_condition = twa_succ_it->cond(); - acc_cond::mark_t tgba_acceptance_conditions = + twa_succ_iterator* twa_succ_it = + tgba_->succ_iter(source->get_tgba_state()); + for (twa_succ_it->first(); !twa_succ_it->done(); + twa_succ_it->next()) + { + const state* tgba_state = twa_succ_it->dst(); + bdd tgba_condition = twa_succ_it->cond(); + acc_cond::mark_t tgba_acceptance_conditions = twa_succ_it->acc(); - bdd satone_tgba_condition; - while ((satone_tgba_condition = - bdd_satoneset(tgba_condition, - atomic_propositions_set_, bddtrue)) - != bddfalse) - { - tgba_condition -= satone_tgba_condition; + bdd satone_tgba_condition; + while ((satone_tgba_condition = + bdd_satoneset(tgba_condition, + atomic_propositions_set_, bddtrue)) + != bddfalse) + { + tgba_condition -= satone_tgba_condition; - bdd all_props = bddtrue; - bdd dest_condition; + bdd all_props = bddtrue; + bdd dest_condition; - bool is_acc = false; - if (degeneralized) - { - twa_succ_iterator* it = tgba_->succ_iter(tgba_state); - it->first(); - if (!it->done()) - is_acc = it->acc() != 0U; - delete it; - } + bool is_acc = false; + if (degeneralized) + { + twa_succ_iterator* it = tgba_->succ_iter(tgba_state); + it->first(); + if (!it->done()) + is_acc = it->acc() != 0U; + delete it; + } - if (satone_tgba_condition == source->get_tgba_condition()) - while ((dest_condition = - bdd_satoneset(all_props, - atomic_propositions_set_, bddtrue)) - != bddfalse) - { - all_props -= dest_condition; - state_ta_explicit* new_dest = - new state_ta_explicit(tgba_state->clone(), - dest_condition, false, is_acc); - state_ta_explicit* dest = ta->add_state(new_dest); + if (satone_tgba_condition == source->get_tgba_condition()) + while ((dest_condition = + bdd_satoneset(all_props, + atomic_propositions_set_, bddtrue)) + != bddfalse) + { + all_props -= dest_condition; + state_ta_explicit* new_dest = + new state_ta_explicit(tgba_state->clone(), + dest_condition, false, is_acc); + state_ta_explicit* dest = ta->add_state(new_dest); - if (dest != new_dest) - { - // the state dest already exists in the automaton - new_dest->get_tgba_state()->destroy(); - delete new_dest; - } - else - { - todo.push(dest); - } + if (dest != new_dest) + { + // the state dest already exists in the automaton + new_dest->get_tgba_state()->destroy(); + delete new_dest; + } + else + { + todo.push(dest); + } - bdd cs = bdd_setxor(source->get_tgba_condition(), - dest->get_tgba_condition()); - ta->create_transition(source, cs, - tgba_acceptance_conditions, dest); - } - } - tgba_state->destroy(); - } - delete twa_succ_it; - } + bdd cs = bdd_setxor(source->get_tgba_condition(), + dest->get_tgba_condition()); + ta->create_transition(source, cs, + tgba_acceptance_conditions, dest); + } + } + tgba_state->destroy(); + } + delete twa_succ_it; + } if (no_livelock) - return ta; + return ta; state_ta_explicit* artificial_livelock_acc_state = nullptr; trace << "*** build_ta: artificial_livelock_acc_state_mode = ***" - << artificial_livelock_state_mode << std::endl; + << artificial_livelock_state_mode << std::endl; if (artificial_livelock_state_mode) - { - single_pass_emptiness_check = true; - artificial_livelock_acc_state = - new state_ta_explicit(ta->get_tgba()->get_init_state(), bddtrue, - false, false, true, nullptr); - trace - << "*** build_ta: artificial_livelock_acc_state = ***" - << artificial_livelock_acc_state << std::endl; - } + { + single_pass_emptiness_check = true; + artificial_livelock_acc_state = + new state_ta_explicit(ta->get_tgba()->get_init_state(), bddtrue, + false, false, true, nullptr); + trace + << "*** build_ta: artificial_livelock_acc_state = ***" + << artificial_livelock_acc_state << std::endl; + } compute_livelock_acceptance_states(ta, single_pass_emptiness_check, - artificial_livelock_acc_state); + artificial_livelock_acc_state); return ta; } } ta_explicit_ptr tgba_to_ta(const const_twa_ptr& tgba_, bdd atomic_propositions_set_, - bool degeneralized, bool artificial_initial_state_mode, - bool single_pass_emptiness_check, - bool artificial_livelock_state_mode, - bool no_livelock) + bool degeneralized, bool artificial_initial_state_mode, + bool single_pass_emptiness_check, + bool artificial_livelock_state_mode, + bool no_livelock) { ta_explicit_ptr ta; @@ -555,10 +555,10 @@ namespace spot if (artificial_initial_state_mode) { state_ta_explicit* artificial_init_state = - new state_ta_explicit(tgba_init_state->clone(), bddfalse, true); + new state_ta_explicit(tgba_init_state->clone(), bddfalse, true); ta = make_ta_explicit(tgba_, tgba_->acc().num_sets(), - artificial_init_state); + artificial_init_state); } else { @@ -568,8 +568,8 @@ namespace spot // build ta automaton build_ta(ta, atomic_propositions_set_, degeneralized, - single_pass_emptiness_check, artificial_livelock_state_mode, - no_livelock); + single_pass_emptiness_check, artificial_livelock_state_mode, + no_livelock); // (degeneralized=true) => TA if (degeneralized) @@ -589,8 +589,8 @@ namespace spot state_ta_explicit::transitions::iterator it_trans; for (it_trans = trans->begin(); it_trans != trans->end(); - ++it_trans) - (*it_trans)->acceptance_conditions = ta->acc().all_sets(); + ++it_trans) + (*it_trans)->acceptance_conditions = ta->acc().all_sets(); state->set_accepting_state(false); } @@ -604,11 +604,11 @@ namespace spot { auto tgba_init_state = tgba_->get_init_state(); auto artificial_init_state = new state_ta_explicit(tgba_init_state->clone(), - bddfalse, true); + bddfalse, true); tgba_init_state->destroy(); auto tgta = make_tgta_explicit(tgba_, tgba_->acc().num_sets(), - artificial_init_state); + artificial_init_state); // build a Generalized TA automaton involving a single_pass_emptiness_check // (without an artificial livelock state): @@ -625,14 +625,14 @@ namespace spot initial_states_iter->first(); if (initial_states_iter->done()) { - delete initial_states_iter; - return tgta; + delete initial_states_iter; + return tgta; } bdd first_state_condition = initial_states_iter->cond(); delete initial_states_iter; bdd bdd_stutering_transition = bdd_setxor(first_state_condition, - first_state_condition); + first_state_condition); for (it = states_set.begin(); it != states_set.end(); ++it) { @@ -645,13 +645,13 @@ namespace spot if (trans_empty || state->is_accepting_state()) { ta->create_transition(state, bdd_stutering_transition, - ta->acc().all_sets(), state); + ta->acc().all_sets(), state); } } if (state->compare(ta->get_artificial_initial_state())) ta->create_transition(state, bdd_stutering_transition, - 0U, state); + 0U, state); state->set_livelock_accepting_state(false); state->set_accepting_state(false); diff --git a/spot/taalgos/tgba2ta.hh b/spot/taalgos/tgba2ta.hh index 37da3bd65..397bae900 100644 --- a/spot/taalgos/tgba2ta.hh +++ b/spot/taalgos/tgba2ta.hh @@ -83,11 +83,11 @@ namespace spot /// TGBA \a tgba_to_convert. SPOT_API ta_explicit_ptr tgba_to_ta(const const_twa_ptr& tgba_to_convert, bdd atomic_propositions_set, - bool degeneralized = true, - bool artificial_initial_state_mode = true, - bool single_pass_emptiness_check = false, - bool artificial_livelock_state_mode = false, - bool no_livelock = false); + bool degeneralized = true, + bool artificial_initial_state_mode = true, + bool single_pass_emptiness_check = false, + bool artificial_livelock_state_mode = false, + bool no_livelock = false); /// \ingroup tgba_ta /// \brief Build a spot::tgta_explicit* (TGTA) from an LTL formula. @@ -100,5 +100,5 @@ namespace spot /// language as the TGBA \a tgba_to_convert. SPOT_API tgta_explicit_ptr tgba_to_tgta(const const_twa_ptr& tgba_to_convert, - bdd atomic_propositions_set); + bdd atomic_propositions_set); } diff --git a/spot/tl/apcollect.cc b/spot/tl/apcollect.cc index ffc550b2e..65b092470 100644 --- a/spot/tl/apcollect.cc +++ b/spot/tl/apcollect.cc @@ -31,9 +31,9 @@ namespace spot atomic_prop_set res; for (unsigned i = 0; i < n; ++i) { - std::ostringstream p; - p << 'p' << i; - res.insert(formula::ap(p.str())); + std::ostringstream p; + p << 'p' << i; + res.insert(formula::ap(p.str())); } return res; } @@ -44,11 +44,11 @@ namespace spot if (!s) s = new atomic_prop_set; f.traverse([&](const formula& f) - { - if (f.is(op::ap)) - s->insert(f); - return false; - }); + { + if (f.is(op::ap)) + s->insert(f); + return false; + }); return s; } diff --git a/spot/tl/contain.cc b/spot/tl/contain.cc index f787c9906..2ca722ffe 100644 --- a/spot/tl/contain.cc +++ b/spot/tl/contain.cc @@ -65,7 +65,7 @@ namespace spot // Check whether L(l) is a subset of L(g). bool language_containment_checker::contained(formula l, - formula g) + formula g) { if (l == g) return true; @@ -77,7 +77,7 @@ namespace spot // Check whether L(!l) is a subset of L(g). bool language_containment_checker::neg_contained(formula l, - formula g) + formula g) { if (l == g) return false; @@ -92,7 +92,7 @@ namespace spot // Check whether L(l) is a subset of L(!g). bool language_containment_checker::contained_neg(formula l, - formula g) + formula g) { if (l == g) return false; @@ -122,7 +122,7 @@ namespace spot return &i->second; auto e = ltl_to_tgba_fm(f, dict_, exprop_, symb_merge_, - branching_postponement_, fair_loop_approx_); + branching_postponement_, fair_loop_approx_); record_& r = translated_[f]; r.translation = e; return &r; diff --git a/spot/tl/contain.hh b/spot/tl/contain.hh index 359212540..ba43980b5 100644 --- a/spot/tl/contain.hh +++ b/spot/tl/contain.hh @@ -43,9 +43,9 @@ namespace spot /// This class uses spot::ltl_to_tgba_fm to translate LTL /// formulae. See that function for the meaning of these options. language_containment_checker(const bdd_dict_ptr& dict, bool exprop, - bool symb_merge, - bool branching_postponement, - bool fair_loop_approx); + bool symb_merge, + bool branching_postponement, + bool fair_loop_approx); ~language_containment_checker(); diff --git a/spot/tl/dot.cc b/spot/tl/dot.cc index ab99da93d..1f8dbf157 100644 --- a/spot/tl/dot.cc +++ b/spot/tl/dot.cc @@ -37,94 +37,94 @@ namespace spot std::ostringstream* sinks_; dot_printer(std::ostream& os, formula f) - : os_(os), sinks_(new std::ostringstream) - { - os_ << "digraph G {\n"; - rec(f); - os_ << " subgraph atoms {\n rank=sink;\n" - << sinks_->str() << " }\n}\n"; - } + : os_(os), sinks_(new std::ostringstream) + { + os_ << "digraph G {\n"; + rec(f); + os_ << " subgraph atoms {\n rank=sink;\n" + << sinks_->str() << " }\n}\n"; + } ~dot_printer() - { - delete sinks_; - } + { + delete sinks_; + } int rec(formula f) { - auto i = node_.emplace(f, node_.size()); - int src = i.first->second; - if (!i.second) - return src; + auto i = node_.emplace(f, node_.size()); + int src = i.first->second; + if (!i.second) + return src; - op o = f.kind(); - std::string str = (o == op::ap) ? f.ap_name() : f.kindstr(); + op o = f.kind(); + std::string str = (o == op::ap) ? f.ap_name() : f.kindstr(); - if (o == op::ap || f.is_constant()) - *sinks_ << " " << src << " [label=\"" - << str << "\", shape=box];\n"; - else - os_ << " " << src << " [label=\"" << str << "\"];\n"; + if (o == op::ap || f.is_constant()) + *sinks_ << " " << src << " [label=\"" + << str << "\", shape=box];\n"; + else + os_ << " " << src << " [label=\"" << str << "\"];\n"; - int childnum = 0; - switch (o) - { - case op::ff: - case op::tt: - case op::eword: - case op::ap: - case op::Not: - case op::X: - case op::F: - case op::G: - case op::Closure: - case op::NegClosure: - case op::NegClosureMarked: - case op::Or: - case op::OrRat: - case op::And: - case op::AndRat: - case op::AndNLM: - case op::Star: - case op::FStar: - childnum = 0; // No number for children - break; - case op::Xor: - case op::Implies: - case op::Equiv: - case op::U: - case op::R: - case op::W: - case op::M: - case op::EConcat: - case op::EConcatMarked: - case op::UConcat: - childnum = -2; // L and R markers - break; - case op::Concat: - case op::Fusion: - childnum = 1; // Numbered children - break; - } + int childnum = 0; + switch (o) + { + case op::ff: + case op::tt: + case op::eword: + case op::ap: + case op::Not: + case op::X: + case op::F: + case op::G: + case op::Closure: + case op::NegClosure: + case op::NegClosureMarked: + case op::Or: + case op::OrRat: + case op::And: + case op::AndRat: + case op::AndNLM: + case op::Star: + case op::FStar: + childnum = 0; // No number for children + break; + case op::Xor: + case op::Implies: + case op::Equiv: + case op::U: + case op::R: + case op::W: + case op::M: + case op::EConcat: + case op::EConcatMarked: + case op::UConcat: + childnum = -2; // L and R markers + break; + case op::Concat: + case op::Fusion: + childnum = 1; // Numbered children + break; + } - for (auto c: f) - { - // Do not merge the next two lines, as there is no - // guarantee that rec will be called before we start - // printing the transition. - int dst = rec(c); - os_ << " " << src << " -> " << dst; - if (childnum > 0) - os_ << " [taillabel=\"" << childnum << "\"]"; - if (childnum == -2) - os_ << " [taillabel=\"L\"]"; - else if (childnum == -1) - os_ << " [taillabel=\"R\"]"; - os_ << ";\n"; - ++childnum; - } + for (auto c: f) + { + // Do not merge the next two lines, as there is no + // guarantee that rec will be called before we start + // printing the transition. + int dst = rec(c); + os_ << " " << src << " -> " << dst; + if (childnum > 0) + os_ << " [taillabel=\"" << childnum << "\"]"; + if (childnum == -2) + os_ << " [taillabel=\"L\"]"; + else if (childnum == -1) + os_ << " [taillabel=\"R\"]"; + os_ << ";\n"; + ++childnum; + } - return src; + return src; } }; } diff --git a/spot/tl/exclusive.cc b/spot/tl/exclusive.cc index 5d000721f..abeed73a3 100644 --- a/spot/tl/exclusive.cc +++ b/spot/tl/exclusive.cc @@ -33,66 +33,66 @@ namespace spot std::vector group; auto start = arg; while (*start) - { - while (*start == ' ' || *start == '\t') - ++start; - if (!*start) - break; - if (*start == ',') - { - std::string s = "unexpected ',' in "; - s += arg; - throw std::invalid_argument(s); - } - if (*start == '"') - { - ++start; - auto end = start; - while (*end && *end != '"') - { - if (*end == '\\') - ++end; - ++end; - } - if (!*end) - { - std::string s = "missing closing '\"' in "; - s += arg; - throw std::invalid_argument(s); - } - std::string ap(start, end - start); - group.emplace_back(formula::ap(ap)); - do - ++end; - while (*end == ' ' || *end == '\t'); - if (*end && *end != ',') - { - std::string s = "unexpected character '"; - s += *end; - s += "' in "; - s += arg; - throw std::invalid_argument(s); - } - if (*end == ',') - ++end; - start = end; - } - else - { - auto end = start; - while (*end && *end != ',') - ++end; - auto rend = end; - while (rend > start && (rend[-1] == ' ' || rend[-1] == '\t')) - --rend; - std::string ap(start, rend - start); - group.emplace_back(formula::ap(ap)); - if (*end == ',') - start = end + 1; - else - break; - } - } + { + while (*start == ' ' || *start == '\t') + ++start; + if (!*start) + break; + if (*start == ',') + { + std::string s = "unexpected ',' in "; + s += arg; + throw std::invalid_argument(s); + } + if (*start == '"') + { + ++start; + auto end = start; + while (*end && *end != '"') + { + if (*end == '\\') + ++end; + ++end; + } + if (!*end) + { + std::string s = "missing closing '\"' in "; + s += arg; + throw std::invalid_argument(s); + } + std::string ap(start, end - start); + group.emplace_back(formula::ap(ap)); + do + ++end; + while (*end == ' ' || *end == '\t'); + if (*end && *end != ',') + { + std::string s = "unexpected character '"; + s += *end; + s += "' in "; + s += arg; + throw std::invalid_argument(s); + } + if (*end == ',') + ++end; + start = end; + } + else + { + auto end = start; + while (*end && *end != ',') + ++end; + auto rend = end; + while (rend > start && (rend[-1] == ' ' || rend[-1] == '\t')) + --rend; + std::string ap(start, rend - start); + group.emplace_back(formula::ap(ap)); + if (*end == ',') + start = end + 1; + else + break; + } + } return group; } } @@ -126,16 +126,16 @@ namespace spot for (auto& g: groups) { - group.clear(); + group.clear(); - for (auto ap: g) - if (s->find(ap) != s->end()) - group.push_back(ap); + for (auto ap: g) + if (s->find(ap) != s->end()) + group.push_back(ap); - unsigned s = group.size(); - for (unsigned j = 0; j < s; ++j) - for (unsigned k = j + 1; k < s; ++k) - v.push_back(nand(group[j], group[k])); + unsigned s = group.size(); + for (unsigned j = 0; j < s; ++j) + for (unsigned k = j + 1; k < s; ++k) + v.push_back(nand(group[j], group[k])); }; delete s; @@ -143,15 +143,15 @@ namespace spot } twa_graph_ptr exclusive_ap::constrain(const_twa_graph_ptr aut, - bool simplify_guards) const + bool simplify_guards) const { // Compute the support of the automaton. bdd support = bddtrue; { std::set bdd_seen; for (auto& t: aut->edges()) - if (bdd_seen.insert(t.cond.id()).second) - support &= bdd_support(t.cond); + if (bdd_seen.insert(t.cond.id()).second) + support &= bdd_support(t.cond); } bdd restrict = bddtrue; @@ -160,19 +160,19 @@ namespace spot std::vector group; for (auto& g: groups) { - group.clear(); + group.clear(); - for (auto ap: g) - { - int v = d->has_registered_proposition(ap, aut); - if (v >= 0) - group.push_back(bdd_nithvar(v)); - } + for (auto ap: g) + { + int v = d->has_registered_proposition(ap, aut); + if (v >= 0) + group.push_back(bdd_nithvar(v)); + } - unsigned s = group.size(); - for (unsigned j = 0; j < s; ++j) - for (unsigned k = j + 1; k < s; ++k) - restrict &= group[j] | group[k]; + unsigned s = group.size(); + for (unsigned j = 0; j < s; ++j) + for (unsigned k = j + 1; k < s; ++k) + restrict &= group[j] | group[k]; } twa_graph_ptr res = make_twa_graph(aut->get_dict()); @@ -181,26 +181,26 @@ namespace spot res->copy_acceptance_of(aut); if (simplify_guards) { - transform_accessible(aut, res, [&](unsigned, bdd& cond, - acc_cond::mark_t&, unsigned) - { - minato_isop isop(cond & restrict, - cond | !restrict, - true); - bdd res = bddfalse; - bdd cube = bddfalse; - while ((cube = isop.next()) != bddfalse) - res |= cube; - cond = res; - }); + transform_accessible(aut, res, [&](unsigned, bdd& cond, + acc_cond::mark_t&, unsigned) + { + minato_isop isop(cond & restrict, + cond | !restrict, + true); + bdd res = bddfalse; + bdd cube = bddfalse; + while ((cube = isop.next()) != bddfalse) + res |= cube; + cond = res; + }); } else { - transform_accessible(aut, res, [&](unsigned, bdd& cond, - acc_cond::mark_t&, unsigned) - { - cond &= restrict; - }); + transform_accessible(aut, res, [&](unsigned, bdd& cond, + acc_cond::mark_t&, unsigned) + { + cond &= restrict; + }); } return res; } diff --git a/spot/tl/exclusive.hh b/spot/tl/exclusive.hh index 484fc213b..b0310c34d 100644 --- a/spot/tl/exclusive.hh +++ b/spot/tl/exclusive.hh @@ -41,6 +41,6 @@ namespace spot formula constrain(formula f) const; twa_graph_ptr constrain(const_twa_graph_ptr aut, - bool simplify_guards = false) const; + bool simplify_guards = false) const; }; } diff --git a/spot/tl/formula.cc b/spot/tl/formula.cc index 11335a27a..0ca67bb1e 100644 --- a/spot/tl/formula.cc +++ b/spot/tl/formula.cc @@ -48,41 +48,41 @@ namespace spot { bool operator()(const fnode* l, const fnode* r) const { - op opl = l->kind(); - op opr = r->kind(); - if (opl != opr) - return opl < opr; + op opl = l->kind(); + op opr = r->kind(); + if (opl != opr) + return opl < opr; - if (SPOT_UNLIKELY(opl == op::Star || opl == op::FStar)) - { - { - auto minl = l->min(); - auto minr = r->min(); - if (minl != minr) - return minl < minr; - } - { - auto maxl = l->max(); - auto maxr = r->max(); - if (maxl != maxr) - return maxl < maxr; - } - } - else - { - auto szl = l->size(); - auto szr = r->size(); - if (szl != szr) - return szl < szr; - } + if (SPOT_UNLIKELY(opl == op::Star || opl == op::FStar)) + { + { + auto minl = l->min(); + auto minr = r->min(); + if (minl != minr) + return minl < minr; + } + { + auto maxl = l->max(); + auto maxr = r->max(); + if (maxl != maxr) + return maxl < maxr; + } + } + else + { + auto szl = l->size(); + auto szr = r->size(); + if (szl != szr) + return szl < szr; + } - auto el = l->end(); - auto ir = r->begin(); - for (auto il = l->begin(); il != el; ++il, ++ir) - if (*il != *ir) - return (*il)->id() < (*ir)->id(); + auto el = l->end(); + auto ir = r->begin(); + for (auto il = l->begin(); il != el; ++il, ++ir) + if (*il != *ir) + return (*il)->id() < (*ir)->id(); - return false; + return false; } }; @@ -102,17 +102,17 @@ namespace spot vec b; vec::iterator i = v.begin(); while (i != v.end()) - { - if ((*i)->is_boolean()) - { - b.push_back(*i); - i = v.erase(i); - } - else - { - ++i; - } - } + { + if ((*i)->is_boolean()) + { + b.push_back(*i); + i = v.erase(i); + } + else + { + ++i; + } + } // - AndNLM(Exps1...,Bool1,Exps2...,Bool2,Exps3...) = // AndNLM(And(Bool1,Bool2),Exps1...,Exps2...,Exps3...) // - AndRat(Exps1...,Bool1,Exps2...,Bool2,Exps3...) = @@ -120,7 +120,7 @@ namespace spot // - OrRat(Exps1...,Bool1,Exps2...,Bool2,Exps3...) = // AndRat(Or(Bool1,Bool2),Exps1...,Exps2...,Exps3...) if (!b.empty()) - v.insert(v.begin(), fnode::multop(o, std::move(b))); + v.insert(v.begin(), fnode::multop(o, std::move(b))); } } @@ -129,11 +129,11 @@ namespace spot auto ires = m.uniq.emplace(f); if (!ires.second) { - //(*ires.first)->dump(std::cerr << "UNI: ") << '\n'; - for (auto c: *f) - c->destroy(); - delete f; - return (*ires.first)->clone(); + //(*ires.first)->dump(std::cerr << "UNI: ") << '\n'; + for (auto c: *f) + c->destroy(); + delete f; + return (*ires.first)->clone(); } //f->dump(std::cerr << "INS: ") << '\n'; return f; @@ -144,19 +144,19 @@ namespace spot { if (SPOT_UNLIKELY(is(op::ap))) { - auto i = m.ap2name.find(id()); - auto n = m.name2ap.erase(i->second); - assert(n == 1); - (void)n; - m.ap2name.erase(i); + auto i = m.ap2name.find(id()); + auto n = m.name2ap.erase(i->second); + assert(n == 1); + (void)n; + m.ap2name.erase(i); } else { - auto n = m.uniq.erase(this); - assert(n == 1); - (void)n; - for (auto c: *this) - c->destroy(); + auto n = m.uniq.erase(this); + assert(n == 1); + (void)n; + for (auto c: *this) + c->destroy(); } delete this; } @@ -165,40 +165,40 @@ namespace spot { switch (op_) { -#define C(x) \ - case op::x: \ - return #x; \ - break - C(ff); - C(tt); - C(eword); - C(ap); - C(Not); - C(X); - C(F); - C(G); - C(Closure); - C(NegClosure); - C(NegClosureMarked); - C(Xor); - C(Implies); - C(Equiv); - C(U); - C(R); - C(W); - C(M); - C(EConcat); - C(EConcatMarked); - C(UConcat); - C(Or); - C(OrRat); - C(And); - C(AndRat); - C(AndNLM); - C(Concat); - C(Fusion); - C(Star); - C(FStar); +#define C(x) \ + case op::x: \ + return #x; \ + break + C(ff); + C(tt); + C(eword); + C(ap); + C(Not); + C(X); + C(F); + C(G); + C(Closure); + C(NegClosure); + C(NegClosureMarked); + C(Xor); + C(Implies); + C(Equiv); + C(U); + C(R); + C(W); + C(M); + C(EConcat); + C(EConcatMarked); + C(UConcat); + C(Or); + C(OrRat); + C(And); + C(AndRat); + C(AndNLM); + C(Concat); + C(Fusion); + C(Star); + C(FStar); #undef C } SPOT_UNREACHABLE(); @@ -215,40 +215,40 @@ namespace spot vec inlined; vec::iterator i = v.begin(); while (i != v.end()) - { - // Some simplification routines erase terms using null - // pointers that we must ignore. - if ((*i) == nullptr) - { - // FIXME: For commutative operators we should replace - // the pointer by the first non-null value at the end - // of the array instead of calling erase. - i = v.erase(i); - continue; - } - if ((*i)->is(o)) - { - unsigned ps = (*i)->size(); - for (unsigned n = 0; n < ps; ++n) - inlined.push_back((*i)->nth(n)->clone()); - (*i)->destroy(); - // FIXME: Do not use erase. See previous FIXME. - i = v.erase(i); - continue; - } - // All operators except "Concat" and "Fusion" are - // commutative, so we just keep a list of the inlined - // arguments that should later be added to the vector. - // For concat we have to keep track of the order of - // all the arguments. - if (o == op::Concat || o == op::Fusion) - inlined.push_back(*i); - ++i; - } + { + // Some simplification routines erase terms using null + // pointers that we must ignore. + if ((*i) == nullptr) + { + // FIXME: For commutative operators we should replace + // the pointer by the first non-null value at the end + // of the array instead of calling erase. + i = v.erase(i); + continue; + } + if ((*i)->is(o)) + { + unsigned ps = (*i)->size(); + for (unsigned n = 0; n < ps; ++n) + inlined.push_back((*i)->nth(n)->clone()); + (*i)->destroy(); + // FIXME: Do not use erase. See previous FIXME. + i = v.erase(i); + continue; + } + // All operators except "Concat" and "Fusion" are + // commutative, so we just keep a list of the inlined + // arguments that should later be added to the vector. + // For concat we have to keep track of the order of + // all the arguments. + if (o == op::Concat || o == op::Fusion) + inlined.push_back(*i); + ++i; + } if (o == op::Concat || o == op::Fusion) - v.swap(inlined); + v.swap(inlined); else - v.insert(v.end(), inlined.begin(), inlined.end()); + v.insert(v.end(), inlined.begin(), inlined.end()); } if (o != op::Concat && o != op::Fusion) @@ -264,145 +264,145 @@ namespace spot switch (o) { case op::And: - neutral = tt(); - neutral2 = nullptr; - abs = ff(); - abs2 = nullptr; - weak_abs = nullptr; - break; + neutral = tt(); + neutral2 = nullptr; + abs = ff(); + abs2 = nullptr; + weak_abs = nullptr; + break; case op::AndRat: - neutral = one_star(); - neutral2 = nullptr; - abs = ff(); - abs2 = nullptr; - weak_abs = eword(); - gather_bool(v, op::And); - break; + neutral = one_star(); + neutral2 = nullptr; + abs = ff(); + abs2 = nullptr; + weak_abs = eword(); + gather_bool(v, op::And); + break; case op::AndNLM: - neutral = eword(); - neutral2 = nullptr; - abs = ff(); - abs2 = nullptr; - weak_abs = tt(); - gather_bool(v, op::And); - break; + neutral = eword(); + neutral2 = nullptr; + abs = ff(); + abs2 = nullptr; + weak_abs = tt(); + gather_bool(v, op::And); + break; case op::Or: - neutral = ff(); - neutral2 = nullptr; - abs = tt(); - abs2 = nullptr; - weak_abs = nullptr; - break; + neutral = ff(); + neutral2 = nullptr; + abs = tt(); + abs2 = nullptr; + weak_abs = nullptr; + break; case op::OrRat: - neutral = ff(); - neutral2 = nullptr; - abs = one_star(); - abs2 = nullptr; - weak_abs = nullptr; - gather_bool(v, op::Or); - break; + neutral = ff(); + neutral2 = nullptr; + abs = one_star(); + abs2 = nullptr; + weak_abs = nullptr; + gather_bool(v, op::Or); + break; case op::Concat: - neutral = eword(); - neutral2 = nullptr; - abs = ff(); - abs2 = nullptr; - weak_abs = nullptr; + neutral = eword(); + neutral2 = nullptr; + abs = ff(); + abs2 = nullptr; + weak_abs = nullptr; - // - Concat(Exps1...,FExps2...,1[*],FExps3...,Exps4) = - // Concat(Exps1...,1[*],Exps4) - // If FExps2... and FExps3 all accept [*0]. - { - vec::iterator i = v.begin(); - const fnode* os = one_star(); - while (i != v.end()) - { - while (i != v.end() && !(*i)->accepts_eword()) - ++i; - if (i == v.end()) - break; - vec::iterator b = i; - // b is the first expressions that accepts [*0]. - // let's find more, and locate the position of - // 1[*] at the same time. - bool os_seen = false; - do - { - os_seen |= (*i == os); - ++i; - } - while (i != v.end() && (*i)->accepts_eword()); + // - Concat(Exps1...,FExps2...,1[*],FExps3...,Exps4) = + // Concat(Exps1...,1[*],Exps4) + // If FExps2... and FExps3 all accept [*0]. + { + vec::iterator i = v.begin(); + const fnode* os = one_star(); + while (i != v.end()) + { + while (i != v.end() && !(*i)->accepts_eword()) + ++i; + if (i == v.end()) + break; + vec::iterator b = i; + // b is the first expressions that accepts [*0]. + // let's find more, and locate the position of + // 1[*] at the same time. + bool os_seen = false; + do + { + os_seen |= (*i == os); + ++i; + } + while (i != v.end() && (*i)->accepts_eword()); - if (os_seen) // [b..i) is a range that contains [*]. - { - // Place [*] at the start of the range, and erase - // all other formulae. - (*b)->destroy(); - *b++ = os->clone(); - for (vec::iterator c = b; c < i; ++c) - (*c)->destroy(); - i = v.erase(b, i); - } - } - } + if (os_seen) // [b..i) is a range that contains [*]. + { + // Place [*] at the start of the range, and erase + // all other formulae. + (*b)->destroy(); + *b++ = os->clone(); + for (vec::iterator c = b; c < i; ++c) + (*c)->destroy(); + i = v.erase(b, i); + } + } + } - break; + break; case op::Fusion: - neutral = tt(); - neutral2 = nullptr; - abs = ff(); - abs2 = eword(); - weak_abs = nullptr; + neutral = tt(); + neutral2 = nullptr; + abs = ff(); + abs2 = eword(); + weak_abs = nullptr; - // Make a first pass to group adjacent Boolean formulae. - // - Fusion(Exps1...,BoolExp1...BoolExpN,Exps2,Exps3...) = - // Fusion(Exps1...,And(BoolExp1...BoolExpN),Exps2,Exps3...) - { - vec::iterator i = v.begin(); - while (i != v.end()) - { - if ((*i)->is_boolean()) - { - vec::iterator first = i; - ++i; - if (i == v.end()) - break; - if (!(*i)->is_boolean()) - { - ++i; - continue; - } - do - ++i; - while (i != v.end() && (*i)->is_boolean()); - // We have at least two adjacent Boolean formulae. - // Replace the first one by the conjunction of all. - // FIXME: Investigate the removal of the temporary - // vector, by allowing range to be passed to - // multop() instead of entire containers. We - // should then able to do - // *first = multop(op::And, first, i); - // i = v.erase(first + 1, i); - vec b; - b.insert(b.begin(), first, i); - i = v.erase(first + 1, i); - *first = multop(op::And, b); - } - else - { - ++i; - } - } - } + // Make a first pass to group adjacent Boolean formulae. + // - Fusion(Exps1...,BoolExp1...BoolExpN,Exps2,Exps3...) = + // Fusion(Exps1...,And(BoolExp1...BoolExpN),Exps2,Exps3...) + { + vec::iterator i = v.begin(); + while (i != v.end()) + { + if ((*i)->is_boolean()) + { + vec::iterator first = i; + ++i; + if (i == v.end()) + break; + if (!(*i)->is_boolean()) + { + ++i; + continue; + } + do + ++i; + while (i != v.end() && (*i)->is_boolean()); + // We have at least two adjacent Boolean formulae. + // Replace the first one by the conjunction of all. + // FIXME: Investigate the removal of the temporary + // vector, by allowing range to be passed to + // multop() instead of entire containers. We + // should then able to do + // *first = multop(op::And, first, i); + // i = v.erase(first + 1, i); + vec b; + b.insert(b.begin(), first, i); + i = v.erase(first + 1, i); + *first = multop(op::And, b); + } + else + { + ++i; + } + } + } - break; + break; default: - neutral = nullptr; - neutral2 = nullptr; - abs = nullptr; - abs2 = nullptr; - weak_abs = nullptr; - break; + neutral = nullptr; + neutral2 = nullptr; + abs = nullptr; + abs2 = nullptr; + weak_abs = nullptr; + break; } // Remove duplicates (except for Concat and Fusion). We can't use @@ -413,170 +413,170 @@ namespace spot vec::iterator i = v.begin(); bool weak_abs_seen = false; while (i != v.end()) - { - if ((*i == neutral) || (*i == neutral2) || (*i == last)) - { - (*i)->destroy(); - i = v.erase(i); - } - else if (*i == abs || *i == abs2) - { - for (i = v.begin(); i != v.end(); ++i) - (*i)->destroy(); - return abs->clone(); - } - else - { - weak_abs_seen |= (*i == weak_abs); - if (o != op::Concat && o != op::Fusion) - // Don't remove duplicates - last = *i; - ++i; - } - } + { + if ((*i == neutral) || (*i == neutral2) || (*i == last)) + { + (*i)->destroy(); + i = v.erase(i); + } + else if (*i == abs || *i == abs2) + { + for (i = v.begin(); i != v.end(); ++i) + (*i)->destroy(); + return abs->clone(); + } + else + { + weak_abs_seen |= (*i == weak_abs); + if (o != op::Concat && o != op::Fusion) + // Don't remove duplicates + last = *i; + ++i; + } + } if (weak_abs_seen) - { - if (o == op::AndRat) - { - // We have a* && [*0] && c = 0 - // and a* && [*0] && c* = [*0] - // So if [*0] has been seen, check if alls term - // recognize the empty word. - bool acc_eword = true; - for (i = v.begin(); i != v.end(); ++i) - { - acc_eword &= (*i)->accepts_eword(); - (*i)->destroy(); - } - if (acc_eword) - return weak_abs; - else - return abs; - } - else - { - // Similarly, a* & 1 & (c;d) = c;d - // a* & 1 & c* = 1 - assert(o == op::AndNLM); - vec tmp; - for (auto i: v) - { - if (i == weak_abs) - continue; - if (i->accepts_eword()) - { - i->destroy(); - continue; - } - tmp.push_back(i); - } - if (tmp.empty()) - tmp.push_back(weak_abs); - v.swap(tmp); - } - } + { + if (o == op::AndRat) + { + // We have a* && [*0] && c = 0 + // and a* && [*0] && c* = [*0] + // So if [*0] has been seen, check if alls term + // recognize the empty word. + bool acc_eword = true; + for (i = v.begin(); i != v.end(); ++i) + { + acc_eword &= (*i)->accepts_eword(); + (*i)->destroy(); + } + if (acc_eword) + return weak_abs; + else + return abs; + } + else + { + // Similarly, a* & 1 & (c;d) = c;d + // a* & 1 & c* = 1 + assert(o == op::AndNLM); + vec tmp; + for (auto i: v) + { + if (i == weak_abs) + continue; + if (i->accepts_eword()) + { + i->destroy(); + continue; + } + tmp.push_back(i); + } + if (tmp.empty()) + tmp.push_back(weak_abs); + v.swap(tmp); + } + } else if (o == op::Concat || o == op::Fusion) - { - // Perform an extra loop to merge starable items. - // f;f -> f[*2] - // f;f[*i..j] -> f[*i+1..j+1] - // f[*i..j];f -> f[*i+1..j+1] - // f[*i..j];f[*k..l] -> f[*i+k..j+l] - // same for FStar: - // f:f -> f[:*2] - // f:f[*i..j] -> f[:*i+1..j+1] - // f[:*i..j];f -> f[:*i+1..j+1] - // f[:*i..j];f[:*k..l] -> f[:*i+k..j+l] - op bop = o == op::Concat ? op::Star : op::FStar; - i = v.begin(); - while (i != v.end()) - { - vec::iterator fpos = i; - const fnode* f; - unsigned min; - unsigned max; - bool changed = false; - if ((*i)->is(bop)) - { - f = (*i)->nth(0); - min = (*i)->min(); - max = (*i)->max(); - } - else - { - f = *i; - min = max = 1; - } + { + // Perform an extra loop to merge starable items. + // f;f -> f[*2] + // f;f[*i..j] -> f[*i+1..j+1] + // f[*i..j];f -> f[*i+1..j+1] + // f[*i..j];f[*k..l] -> f[*i+k..j+l] + // same for FStar: + // f:f -> f[:*2] + // f:f[*i..j] -> f[:*i+1..j+1] + // f[:*i..j];f -> f[:*i+1..j+1] + // f[:*i..j];f[:*k..l] -> f[:*i+k..j+l] + op bop = o == op::Concat ? op::Star : op::FStar; + i = v.begin(); + while (i != v.end()) + { + vec::iterator fpos = i; + const fnode* f; + unsigned min; + unsigned max; + bool changed = false; + if ((*i)->is(bop)) + { + f = (*i)->nth(0); + min = (*i)->min(); + max = (*i)->max(); + } + else + { + f = *i; + min = max = 1; + } - ++i; - while (i != v.end()) - { - const fnode* f2; - unsigned min2; - unsigned max2; - if ((*i)->is(bop)) - { - f2 = (*i)->nth(0); - if (f2 != f) - break; - min2 = (*i)->min(); - max2 = (*i)->max(); - } - else - { - f2 = *i; - if (f2 != f) - break; - min2 = max2 = 1; - } - if (min2 == unbounded()) - min = unbounded(); - else if (min != unbounded()) - min += min2; - if (max2 == unbounded()) - max = unbounded(); - else if (max != unbounded()) - max += max2; - (*i)->destroy(); - i = v.erase(i); - changed = true; - } - if (changed) - { - const fnode* newfs = bunop(bop, f->clone(), min, max); - (*fpos)->destroy(); - *fpos = newfs; - } - } - } + ++i; + while (i != v.end()) + { + const fnode* f2; + unsigned min2; + unsigned max2; + if ((*i)->is(bop)) + { + f2 = (*i)->nth(0); + if (f2 != f) + break; + min2 = (*i)->min(); + max2 = (*i)->max(); + } + else + { + f2 = *i; + if (f2 != f) + break; + min2 = max2 = 1; + } + if (min2 == unbounded()) + min = unbounded(); + else if (min != unbounded()) + min += min2; + if (max2 == unbounded()) + max = unbounded(); + else if (max != unbounded()) + max += max2; + (*i)->destroy(); + i = v.erase(i); + changed = true; + } + if (changed) + { + const fnode* newfs = bunop(bop, f->clone(), min, max); + (*fpos)->destroy(); + *fpos = newfs; + } + } + } } vec::size_type s = v.size(); if (s == 0) { - assert(neutral != nullptr); - return neutral->clone(); + assert(neutral != nullptr); + return neutral->clone(); } else if (s == 1) { - // Simply replace Multop(Op,X) by X. - // Except we should never reduce the - // arguments of a Fusion operator to - // a list with a single formula that - // accepts [*0]. - const fnode* res = v[0]; - if (o != op::Fusion || orig_size == 1 - || !res->accepts_eword()) - return res; - // If Fusion(f, ...) reduces to Fusion(f), emit Fusion(1,f). - // to ensure that [*0] is not accepted. - v.insert(v.begin(), tt()); + // Simply replace Multop(Op,X) by X. + // Except we should never reduce the + // arguments of a Fusion operator to + // a list with a single formula that + // accepts [*0]. + const fnode* res = v[0]; + if (o != op::Fusion || orig_size == 1 + || !res->accepts_eword()) + return res; + // If Fusion(f, ...) reduces to Fusion(f), emit Fusion(1,f). + // to ensure that [*0] is not accepted. + v.insert(v.begin(), tt()); } auto mem = operator new(sizeof(fnode) - + (v.size() - 1)*sizeof(*children)); + + (v.size() - 1)*sizeof(*children)); return unique(new(mem) fnode(o, v.begin(), v.end())); } @@ -589,13 +589,13 @@ namespace spot switch (o) { case op::Star: - neutral = eword(); - break; + neutral = eword(); + break; case op::FStar: - neutral = tt(); - break; + neutral = tt(); + break; default: - SPOT_UNREACHABLE(); + SPOT_UNREACHABLE(); } @@ -606,93 +606,93 @@ namespace spot // - [*0][:*min..max] = 0 if min > 0 if (child->is_eword()) switch (o) - { - case op::Star: - return neutral; - case op::FStar: - if (min == 0) - return neutral; - else - return ff(); - default: - SPOT_UNREACHABLE(); - } + { + case op::Star: + return neutral; + case op::FStar: + if (min == 0) + return neutral; + else + return ff(); + default: + SPOT_UNREACHABLE(); + } // - 0[*0..max] = [*0] // - 0[*min..max] = 0 if min > 0 // - b[:*0..max] = 1 // - b[:*min..max] = 0 if min > 0 if (child->is_ff() - || (o == op::FStar && child->is_boolean())) + || (o == op::FStar && child->is_boolean())) { - if (min == 0) - { - child->destroy(); - return neutral; - } - return child; + if (min == 0) + { + child->destroy(); + return neutral; + } + return child; } // - Exp[*0] = [*0] // - Exp[:*0] = 1 if (max == 0) { - child->destroy(); - return neutral; + child->destroy(); + return neutral; } // - Exp[*1] = Exp // - Exp[:*1] = Exp if Exp does not accept [*0] if (min == 1 && max == 1) if (o == op::Star || !child->accepts_eword()) - return child; + return child; // - Exp[*i..j][*k..l] = Exp[*ik..jl] if i*(k+1)<=jk+1. // - Exp[:*i..j][:*k..l] = Exp[:*ik..jl] if i*(k+1)<=jk+1. if (child->is(o)) { - unsigned i = child->min(); - unsigned j = child->max(); + unsigned i = child->min(); + unsigned j = child->max(); - // Exp has to be true between i*min and j*min - // then between i*(min+1) and j*(min+1) - // ... - // finally between i*max and j*max - // - // We can merge these intervals into [i*min..j*max] iff the - // first are adjacent or overlap, i.e. iff - // i*(min+1) <= j*min+1. - // (Because i<=j, this entails that the other intervals also - // overlap). + // Exp has to be true between i*min and j*min + // then between i*(min+1) and j*(min+1) + // ... + // finally between i*max and j*max + // + // We can merge these intervals into [i*min..j*max] iff the + // first are adjacent or overlap, i.e. iff + // i*(min+1) <= j*min+1. + // (Because i<=j, this entails that the other intervals also + // overlap). - const fnode* exp = child->nth(0); - if (j == unbounded()) - { - min *= i; - max = unbounded(); + const fnode* exp = child->nth(0); + if (j == unbounded()) + { + min *= i; + max = unbounded(); - // Exp[*min..max] - exp->clone(); - child->destroy(); - child = exp; - } - else - { - if (i * (min + 1) <= (j * min) + 1) - { - min *= i; - if (max != unbounded()) - { - if (j == unbounded()) - max = unbounded(); - else - max *= j; - } - exp->clone(); - child->destroy(); - child = exp; - } - } + // Exp[*min..max] + exp->clone(); + child->destroy(); + child = exp; + } + else + { + if (i * (min + 1) <= (j * min) + 1) + { + min *= i; + if (max != unbounded()) + { + if (j == unbounded()) + max = unbounded(); + else + max *= j; + } + exp->clone(); + child->destroy(); + child = exp; + } + } } return unique(new fnode(o, child, min, max)); @@ -706,86 +706,86 @@ namespace spot { case op::F: case op::G: - { - // F and G are idempotent. - if (f->is(o)) - return f; + { + // F and G are idempotent. + if (f->is(o)) + return f; - // F(0) = G(0) = 0 - // F(1) = G(1) = 1 - if (f->is_ff() || f->is_tt()) - return f; + // F(0) = G(0) = 0 + // F(1) = G(1) = 1 + if (f->is_ff() || f->is_tt()) + return f; - assert(!f->is_eword()); - } - break; + assert(!f->is_eword()); + } + break; case op::Not: - { - // !1 = 0 - if (f->is_tt()) - return ff(); - // !0 = 1 - if (f->is_ff()) - return tt(); - // ![*0] = 1[+] - if (f->is_eword()) - return bunop(op::Star, tt(), 1); + { + // !1 = 0 + if (f->is_tt()) + return ff(); + // !0 = 1 + if (f->is_ff()) + return tt(); + // ![*0] = 1[+] + if (f->is_eword()) + return bunop(op::Star, tt(), 1); - auto fop = f->kind(); - // "Not" is an involution. - if (fop == o) - { - auto c = f->nth(0)->clone(); - f->destroy(); - return c; - } - // !Closure(Exp) = NegClosure(Exp) - if (fop == op::Closure) - { - const fnode* c = unop(op::NegClosure, f->nth(0)->clone()); - f->destroy(); - return c; - } - // !NegClosure(Exp) = Closure(Exp) - if (fop == op::NegClosure || fop == op::NegClosureMarked) - { - const fnode* c = unop(op::Closure, f->nth(0)->clone()); - f->destroy(); - return c; - } - break; - } + auto fop = f->kind(); + // "Not" is an involution. + if (fop == o) + { + auto c = f->nth(0)->clone(); + f->destroy(); + return c; + } + // !Closure(Exp) = NegClosure(Exp) + if (fop == op::Closure) + { + const fnode* c = unop(op::NegClosure, f->nth(0)->clone()); + f->destroy(); + return c; + } + // !NegClosure(Exp) = Closure(Exp) + if (fop == op::NegClosure || fop == op::NegClosureMarked) + { + const fnode* c = unop(op::Closure, f->nth(0)->clone()); + f->destroy(); + return c; + } + break; + } case op::X: - // X(1) = 1, X(0) = 0 - if (f->is_tt() || f->is_ff()) - return f; - assert(!f->is_eword()); - break; + // X(1) = 1, X(0) = 0 + if (f->is_tt() || f->is_ff()) + return f; + assert(!f->is_eword()); + break; case op::Closure: - // {0} = 0, {1} = 1, {b} = b - if (f->is_boolean()) - return f; - // {[*0]} = 0 - if (f->is_eword()) - return ff(); - break; + // {0} = 0, {1} = 1, {b} = b + if (f->is_boolean()) + return f; + // {[*0]} = 0 + if (f->is_eword()) + return ff(); + break; case op::NegClosure: case op::NegClosureMarked: - // {1} = 0 - if (f->is_tt()) - return ff(); - // {0} = 1, {[*0]} = 1 - if (f->is_ff() || f->is_eword()) - return tt(); - // {b} = !b - if (f->is_boolean()) - return unop(op::Not, f); - break; + // {1} = 0 + if (f->is_tt()) + return ff(); + // {0} = 1, {[*0]} = 1 + if (f->is_ff() || f->is_eword()) + return tt(); + // {b} = !b + if (f->is_boolean()) + return unop(op::Not, f); + break; default: - SPOT_UNREACHABLE(); + SPOT_UNREACHABLE(); } return unique(new fnode(o, {f})); @@ -802,190 +802,190 @@ namespace spot switch (o) { case op::Xor: - { - // Xor is commutative: sort operands. - formula_ptr_less_than_bool_first cmp; - if (cmp(second, first)) - std::swap(second, first); - } - // - (1 ^ Exp) = !Exp - // - (0 ^ Exp) = Exp - if (first->is_tt()) - return unop(op::Not, second); - if (first->is_ff()) - return second; - if (first == second) - { - first->destroy(); - second->destroy(); - return ff(); - } - // We expect constants to appear first, because they are - // instantiated first. - assert(!second->is_constant()); - break; + { + // Xor is commutative: sort operands. + formula_ptr_less_than_bool_first cmp; + if (cmp(second, first)) + std::swap(second, first); + } + // - (1 ^ Exp) = !Exp + // - (0 ^ Exp) = Exp + if (first->is_tt()) + return unop(op::Not, second); + if (first->is_ff()) + return second; + if (first == second) + { + first->destroy(); + second->destroy(); + return ff(); + } + // We expect constants to appear first, because they are + // instantiated first. + assert(!second->is_constant()); + break; case op::Equiv: - { - // Equiv is commutative: sort operands. - formula_ptr_less_than_bool_first cmp; - if (cmp(second, first)) - std::swap(second, first); - } - // - (0 <=> Exp) = !Exp - // - (1 <=> Exp) = Exp - // - (Exp <=> Exp) = 1 - if (first->is_ff()) - return unop(op::Not, second); - if (first->is_tt()) - return second; - if (first == second) - { - first->destroy(); - second->destroy(); - return tt(); - } - // We expect constants to appear first, because they are - // instantiated first. - assert(!second->is_constant()); - break; + { + // Equiv is commutative: sort operands. + formula_ptr_less_than_bool_first cmp; + if (cmp(second, first)) + std::swap(second, first); + } + // - (0 <=> Exp) = !Exp + // - (1 <=> Exp) = Exp + // - (Exp <=> Exp) = 1 + if (first->is_ff()) + return unop(op::Not, second); + if (first->is_tt()) + return second; + if (first == second) + { + first->destroy(); + second->destroy(); + return tt(); + } + // We expect constants to appear first, because they are + // instantiated first. + assert(!second->is_constant()); + break; case op::Implies: - // - (1 => Exp) = Exp - // - (0 => Exp) = 1 - // - (Exp => 1) = 1 - // - (Exp => 0) = !Exp - // - (Exp => Exp) = 1 - if (first->is_tt()) - return second; - if (first->is_ff()) - { - second->destroy(); - return tt(); - } - if (second->is_tt()) - { - first->destroy(); - return second; - } - if (second->is_ff()) - return unop(op::Not, first); - if (first == second) - { - first->destroy(); - second->destroy(); - return tt(); - } - break; + // - (1 => Exp) = Exp + // - (0 => Exp) = 1 + // - (Exp => 1) = 1 + // - (Exp => 0) = !Exp + // - (Exp => Exp) = 1 + if (first->is_tt()) + return second; + if (first->is_ff()) + { + second->destroy(); + return tt(); + } + if (second->is_tt()) + { + first->destroy(); + return second; + } + if (second->is_ff()) + return unop(op::Not, first); + if (first == second) + { + first->destroy(); + second->destroy(); + return tt(); + } + break; case op::U: - // - (Exp U 1) = 1 - // - (Exp U 0) = 0 - // - (0 U Exp) = Exp - // - (Exp U Exp) = Exp - if (second->is_tt() - || second->is_ff() - || first->is_ff() - || first == second) - { - first->destroy(); - return second; - } - break; + // - (Exp U 1) = 1 + // - (Exp U 0) = 0 + // - (0 U Exp) = Exp + // - (Exp U Exp) = Exp + if (second->is_tt() + || second->is_ff() + || first->is_ff() + || first == second) + { + first->destroy(); + return second; + } + break; case op::W: - // - (Exp W 1) = 1 - // - (0 W Exp) = Exp - // - (1 W Exp) = 1 - // - (Exp W Exp) = Exp - if (second->is_tt() - || first->is_ff() - || first == second) - { - first->destroy(); - return second; - } - if (first->is_tt()) - { - second->destroy(); - return first; - } - break; + // - (Exp W 1) = 1 + // - (0 W Exp) = Exp + // - (1 W Exp) = 1 + // - (Exp W Exp) = Exp + if (second->is_tt() + || first->is_ff() + || first == second) + { + first->destroy(); + return second; + } + if (first->is_tt()) + { + second->destroy(); + return first; + } + break; case op::R: - // - (Exp R 1) = 1 - // - (Exp R 0) = 0 - // - (1 R Exp) = Exp - // - (Exp R Exp) = Exp - if (second->is_tt() - || second->is_ff() - || first->is_tt() - || first == second) - { - first->destroy(); - return second; - } - break; + // - (Exp R 1) = 1 + // - (Exp R 0) = 0 + // - (1 R Exp) = Exp + // - (Exp R Exp) = Exp + if (second->is_tt() + || second->is_ff() + || first->is_tt() + || first == second) + { + first->destroy(); + return second; + } + break; case op::M: - // - (Exp M 0) = 0 - // - (1 M Exp) = Exp - // - (0 M Exp) = 0 - // - (Exp M Exp) = Exp - if (second->is_ff() - || first->is_tt() - || first == second) - { - first->destroy(); - return second; - } - if (first->is_ff()) - { - second->destroy(); - return first; - } - break; + // - (Exp M 0) = 0 + // - (1 M Exp) = Exp + // - (0 M Exp) = 0 + // - (Exp M Exp) = Exp + if (second->is_ff() + || first->is_tt() + || first == second) + { + first->destroy(); + return second; + } + if (first->is_ff()) + { + second->destroy(); + return first; + } + break; case op::EConcat: case op::EConcatMarked: - // - 0 <>-> Exp = 0 - // - 1 <>-> Exp = Exp - // - [*0] <>-> Exp = 0 - // - Exp <>-> 0 = 0 - // - boolExp <>-> Exp = boolExp & Exp - if (first->is_tt()) - return second; - if (first->is_ff() - || first->is_eword()) - { - second->destroy(); - return ff(); - } - if (second->is_ff()) - { - first->destroy(); - return second; - } - if (first->is_boolean()) - return multop(op::And, {first, second}); - break; + // - 0 <>-> Exp = 0 + // - 1 <>-> Exp = Exp + // - [*0] <>-> Exp = 0 + // - Exp <>-> 0 = 0 + // - boolExp <>-> Exp = boolExp & Exp + if (first->is_tt()) + return second; + if (first->is_ff() + || first->is_eword()) + { + second->destroy(); + return ff(); + } + if (second->is_ff()) + { + first->destroy(); + return second; + } + if (first->is_boolean()) + return multop(op::And, {first, second}); + break; case op::UConcat: - // - 0 []-> Exp = 1 - // - 1 []-> Exp = Exp - // - [*0] []-> Exp = 1 - // - Exp []-> 1 = 1 - // - boolExp []-> Exp = !boolExp | Exp - if (first->is_tt()) - return second; - if (first->is_ff() - || first->is_eword()) - { - second->destroy(); - return tt(); - } - if (second->is_tt()) - { - first->destroy(); - return second; - } - if (first->is_boolean()) - return multop(op::Or, {unop(op::Not, first), second}); - break; + // - 0 []-> Exp = 1 + // - 1 []-> Exp = Exp + // - [*0] []-> Exp = 1 + // - Exp []-> 1 = 1 + // - boolExp []-> Exp = !boolExp | Exp + if (first->is_tt()) + return second; + if (first->is_ff() + || first->is_eword()) + { + second->destroy(); + return tt(); + } + if (second->is_tt()) + { + first->destroy(); + return second; + } + if (first->is_boolean()) + return multop(op::Or, {unop(op::Not, first), second}); + break; default: - SPOT_UNREACHABLE(); + SPOT_UNREACHABLE(); } auto mem = operator new(sizeof(fnode) + sizeof(*children)); @@ -1037,543 +1037,543 @@ namespace spot { case op::ff: case op::tt: - is_.boolean = true; - is_.sugar_free_boolean = true; - is_.in_nenoform = true; - is_.syntactic_si = true; // for LTL (not PSL) - is_.sugar_free_ltl = true; - is_.ltl_formula = true; - is_.psl_formula = true; - is_.sere_formula = true; - is_.finite = true; - is_.eventual = true; - is_.universal = true; - is_.syntactic_safety = true; - is_.syntactic_guarantee = true; - is_.syntactic_obligation = true; - is_.syntactic_recurrence = true; - is_.syntactic_persistence = true; - is_.not_marked = true; - is_.accepting_eword = false; - is_.lbt_atomic_props = true; - is_.spin_atomic_props = true; - break; + is_.boolean = true; + is_.sugar_free_boolean = true; + is_.in_nenoform = true; + is_.syntactic_si = true; // for LTL (not PSL) + is_.sugar_free_ltl = true; + is_.ltl_formula = true; + is_.psl_formula = true; + is_.sere_formula = true; + is_.finite = true; + is_.eventual = true; + is_.universal = true; + is_.syntactic_safety = true; + is_.syntactic_guarantee = true; + is_.syntactic_obligation = true; + is_.syntactic_recurrence = true; + is_.syntactic_persistence = true; + is_.not_marked = true; + is_.accepting_eword = false; + is_.lbt_atomic_props = true; + is_.spin_atomic_props = true; + break; case op::eword: - is_.boolean = false; - is_.sugar_free_boolean = false; - is_.in_nenoform = true; - is_.syntactic_si = true; - is_.sugar_free_ltl = true; - is_.ltl_formula = false; - is_.psl_formula = false; - is_.sere_formula = true; - is_.finite = true; - is_.eventual = false; - is_.syntactic_safety = false; - is_.syntactic_guarantee = false; - is_.syntactic_obligation = false; - is_.syntactic_recurrence = false; - is_.syntactic_persistence = false; - is_.universal = false; - is_.not_marked = true; - is_.accepting_eword = true; - is_.lbt_atomic_props = true; - is_.spin_atomic_props = true; - break; + is_.boolean = false; + is_.sugar_free_boolean = false; + is_.in_nenoform = true; + is_.syntactic_si = true; + is_.sugar_free_ltl = true; + is_.ltl_formula = false; + is_.psl_formula = false; + is_.sere_formula = true; + is_.finite = true; + is_.eventual = false; + is_.syntactic_safety = false; + is_.syntactic_guarantee = false; + is_.syntactic_obligation = false; + is_.syntactic_recurrence = false; + is_.syntactic_persistence = false; + is_.universal = false; + is_.not_marked = true; + is_.accepting_eword = true; + is_.lbt_atomic_props = true; + is_.spin_atomic_props = true; + break; case op::ap: - is_.boolean = true; - is_.sugar_free_boolean = true; - is_.in_nenoform = true; - is_.syntactic_si = true; // Assuming LTL (for PSL a Boolean - // term is not stared will be regarded - // as not stuttering were this - // matters.) - is_.sugar_free_ltl = true; - is_.ltl_formula = true; - is_.psl_formula = true; - is_.sere_formula = true; - is_.finite = true; - is_.eventual = false; - is_.universal = false; - is_.syntactic_safety = true; - is_.syntactic_guarantee = true; - is_.syntactic_obligation = true; - is_.syntactic_recurrence = true; - is_.syntactic_persistence = true; - is_.not_marked = true; - is_.accepting_eword = false; - { - // is_.lbt_atomic_props should be true if the name has the - // form pNN where NN is any number of digit. - const std::string& n = ap_name(); - std::string::const_iterator pos = n.begin(); - bool lbtap = (pos != n.end() && *pos++ == 'p'); - while (lbtap && pos != n.end()) - { - char l = *pos++; - lbtap = (l >= '0' && l <= '9'); - } - is_.lbt_atomic_props = lbtap; - is_.spin_atomic_props = lbtap || is_spin_ap(n.c_str()); - } - break; + is_.boolean = true; + is_.sugar_free_boolean = true; + is_.in_nenoform = true; + is_.syntactic_si = true; // Assuming LTL (for PSL a Boolean + // term is not stared will be regarded + // as not stuttering were this + // matters.) + is_.sugar_free_ltl = true; + is_.ltl_formula = true; + is_.psl_formula = true; + is_.sere_formula = true; + is_.finite = true; + is_.eventual = false; + is_.universal = false; + is_.syntactic_safety = true; + is_.syntactic_guarantee = true; + is_.syntactic_obligation = true; + is_.syntactic_recurrence = true; + is_.syntactic_persistence = true; + is_.not_marked = true; + is_.accepting_eword = false; + { + // is_.lbt_atomic_props should be true if the name has the + // form pNN where NN is any number of digit. + const std::string& n = ap_name(); + std::string::const_iterator pos = n.begin(); + bool lbtap = (pos != n.end() && *pos++ == 'p'); + while (lbtap && pos != n.end()) + { + char l = *pos++; + lbtap = (l >= '0' && l <= '9'); + } + is_.lbt_atomic_props = lbtap; + is_.spin_atomic_props = lbtap || is_spin_ap(n.c_str()); + } + break; case op::Not: - props = children[0]->props; - is_.not_marked = true; - is_.eventual = children[0]->is_universal(); - is_.universal = children[0]->is_eventual(); - is_.in_nenoform = (children[0]->is(op::ap)); - is_.sere_formula = is_.boolean; + props = children[0]->props; + is_.not_marked = true; + is_.eventual = children[0]->is_universal(); + is_.universal = children[0]->is_eventual(); + is_.in_nenoform = (children[0]->is(op::ap)); + is_.sere_formula = is_.boolean; - is_.syntactic_safety = children[0]->is_syntactic_guarantee(); - is_.syntactic_guarantee = children[0]->is_syntactic_safety(); - // is_.syntactic_obligation inherited from child - is_.syntactic_recurrence = children[0]->is_syntactic_persistence(); - is_.syntactic_persistence = children[0]->is_syntactic_recurrence(); + is_.syntactic_safety = children[0]->is_syntactic_guarantee(); + is_.syntactic_guarantee = children[0]->is_syntactic_safety(); + // is_.syntactic_obligation inherited from child + is_.syntactic_recurrence = children[0]->is_syntactic_persistence(); + is_.syntactic_persistence = children[0]->is_syntactic_recurrence(); - is_.accepting_eword = false; - break; + is_.accepting_eword = false; + break; case op::X: - props = children[0]->props; - is_.not_marked = true; - is_.boolean = false; - is_.syntactic_si = false; - is_.sere_formula = false; - // is_.syntactic_safety inherited - // is_.syntactic_guarantee inherited - // is_.syntactic_obligation inherited - // is_.syntactic_recurrence inherited - // is_.syntactic_persistence inherited - is_.accepting_eword = false; - break; + props = children[0]->props; + is_.not_marked = true; + is_.boolean = false; + is_.syntactic_si = false; + is_.sere_formula = false; + // is_.syntactic_safety inherited + // is_.syntactic_guarantee inherited + // is_.syntactic_obligation inherited + // is_.syntactic_recurrence inherited + // is_.syntactic_persistence inherited + is_.accepting_eword = false; + break; case op::F: - props = children[0]->props; - is_.not_marked = true; - is_.boolean = false; - is_.sere_formula = false; - is_.finite = false; - is_.sugar_free_ltl = false; - is_.eventual = true; - is_.syntactic_safety = false; - // is_.syntactic_guarantee inherited - is_.syntactic_obligation = is_.syntactic_guarantee; - is_.syntactic_recurrence = is_.syntactic_guarantee; - // is_.syntactic_persistence inherited - is_.accepting_eword = false; - break; + props = children[0]->props; + is_.not_marked = true; + is_.boolean = false; + is_.sere_formula = false; + is_.finite = false; + is_.sugar_free_ltl = false; + is_.eventual = true; + is_.syntactic_safety = false; + // is_.syntactic_guarantee inherited + is_.syntactic_obligation = is_.syntactic_guarantee; + is_.syntactic_recurrence = is_.syntactic_guarantee; + // is_.syntactic_persistence inherited + is_.accepting_eword = false; + break; case op::G: - props = children[0]->props; - is_.not_marked = true; - is_.boolean = false; - is_.sere_formula = false; - is_.finite = false; - is_.sugar_free_ltl = false; - is_.universal = true; - // is_.syntactic_safety inherited - is_.syntactic_guarantee = false; - is_.syntactic_obligation = is_.syntactic_safety; - // is_.syntactic_recurrence inherited - is_.syntactic_persistence = is_.syntactic_safety; - is_.accepting_eword = false; - break; + props = children[0]->props; + is_.not_marked = true; + is_.boolean = false; + is_.sere_formula = false; + is_.finite = false; + is_.sugar_free_ltl = false; + is_.universal = true; + // is_.syntactic_safety inherited + is_.syntactic_guarantee = false; + is_.syntactic_obligation = is_.syntactic_safety; + // is_.syntactic_recurrence inherited + is_.syntactic_persistence = is_.syntactic_safety; + is_.accepting_eword = false; + break; case op::NegClosure: case op::NegClosureMarked: - props = children[0]->props; - is_.not_marked = (op_ == op::NegClosure); - is_.boolean = false; - is_.ltl_formula = false; - is_.psl_formula = true; - is_.sere_formula = false; - is_.syntactic_safety = is_.finite; - is_.syntactic_guarantee = true; - is_.syntactic_obligation = true; - is_.syntactic_recurrence = true; - is_.syntactic_persistence = true; - is_.accepting_eword = false; - assert(children[0]->is_sere_formula()); - assert(!children[0]->is_boolean()); - break; + props = children[0]->props; + is_.not_marked = (op_ == op::NegClosure); + is_.boolean = false; + is_.ltl_formula = false; + is_.psl_formula = true; + is_.sere_formula = false; + is_.syntactic_safety = is_.finite; + is_.syntactic_guarantee = true; + is_.syntactic_obligation = true; + is_.syntactic_recurrence = true; + is_.syntactic_persistence = true; + is_.accepting_eword = false; + assert(children[0]->is_sere_formula()); + assert(!children[0]->is_boolean()); + break; case op::Closure: - props = children[0]->props; - is_.not_marked = true; - is_.boolean = false; - is_.ltl_formula = false; - is_.psl_formula = true; - is_.sere_formula = false; - is_.syntactic_safety = true; - is_.syntactic_guarantee = is_.finite; - is_.syntactic_obligation = true; - is_.syntactic_recurrence = true; - is_.syntactic_persistence = true; - is_.accepting_eword = false; - assert(children[0]->is_sere_formula()); - assert(!children[0]->is_boolean()); - break; + props = children[0]->props; + is_.not_marked = true; + is_.boolean = false; + is_.ltl_formula = false; + is_.psl_formula = true; + is_.sere_formula = false; + is_.syntactic_safety = true; + is_.syntactic_guarantee = is_.finite; + is_.syntactic_obligation = true; + is_.syntactic_recurrence = true; + is_.syntactic_persistence = true; + is_.accepting_eword = false; + assert(children[0]->is_sere_formula()); + assert(!children[0]->is_boolean()); + break; case op::Xor: case op::Equiv: - props = children[0]->props & children[1]->props; - is_.eventual = false; - is_.universal = false; - is_.sere_formula = is_.boolean; - is_.sugar_free_boolean = false; - is_.in_nenoform = false; - // is_.syntactic_obligation inherited; - is_.accepting_eword = false; - if (is_.syntactic_obligation) - { - // Only formula that are in the intersection of - // guarantee and safety are closed by Xor and <=>. - bool sg = is_.syntactic_safety && is_.syntactic_guarantee; - is_.syntactic_safety = sg; - is_.syntactic_guarantee = sg; - assert(is_.syntactic_recurrence == true); - assert(is_.syntactic_persistence == true); - } - else - { - is_.syntactic_safety = false; - is_.syntactic_guarantee = false; - is_.syntactic_recurrence = false; - is_.syntactic_persistence = false; - } - break; + props = children[0]->props & children[1]->props; + is_.eventual = false; + is_.universal = false; + is_.sere_formula = is_.boolean; + is_.sugar_free_boolean = false; + is_.in_nenoform = false; + // is_.syntactic_obligation inherited; + is_.accepting_eword = false; + if (is_.syntactic_obligation) + { + // Only formula that are in the intersection of + // guarantee and safety are closed by Xor and <=>. + bool sg = is_.syntactic_safety && is_.syntactic_guarantee; + is_.syntactic_safety = sg; + is_.syntactic_guarantee = sg; + assert(is_.syntactic_recurrence == true); + assert(is_.syntactic_persistence == true); + } + else + { + is_.syntactic_safety = false; + is_.syntactic_guarantee = false; + is_.syntactic_recurrence = false; + is_.syntactic_persistence = false; + } + break; case op::Implies: - props = children[0]->props & children[1]->props; - is_.eventual = false; - is_.universal = false; - is_.sere_formula = is_.boolean; - is_.sugar_free_boolean = false; - is_.in_nenoform = false; - is_.syntactic_safety = (children[0]->is_syntactic_guarantee() - && children[1]->is_syntactic_safety()); - is_.syntactic_guarantee = (children[0]->is_syntactic_safety() - && children[1]->is_syntactic_guarantee()); - // is_.syntactic_obligation inherited - is_.syntactic_persistence = children[0]->is_syntactic_recurrence() - && children[1]->is_syntactic_persistence(); - is_.syntactic_recurrence = children[0]->is_syntactic_persistence() - && children[1]->is_syntactic_recurrence(); - is_.accepting_eword = false; - break; + props = children[0]->props & children[1]->props; + is_.eventual = false; + is_.universal = false; + is_.sere_formula = is_.boolean; + is_.sugar_free_boolean = false; + is_.in_nenoform = false; + is_.syntactic_safety = (children[0]->is_syntactic_guarantee() + && children[1]->is_syntactic_safety()); + is_.syntactic_guarantee = (children[0]->is_syntactic_safety() + && children[1]->is_syntactic_guarantee()); + // is_.syntactic_obligation inherited + is_.syntactic_persistence = children[0]->is_syntactic_recurrence() + && children[1]->is_syntactic_persistence(); + is_.syntactic_recurrence = children[0]->is_syntactic_persistence() + && children[1]->is_syntactic_recurrence(); + is_.accepting_eword = false; + break; case op::EConcatMarked: case op::EConcat: - props = children[0]->props & children[1]->props; - is_.not_marked = (op_ != op::EConcatMarked); - is_.ltl_formula = false; - is_.boolean = false; - is_.sere_formula = false; - is_.accepting_eword = false; - is_.psl_formula = true; + props = children[0]->props & children[1]->props; + is_.not_marked = (op_ != op::EConcatMarked); + is_.ltl_formula = false; + is_.boolean = false; + is_.sere_formula = false; + is_.accepting_eword = false; + is_.psl_formula = true; - is_.syntactic_guarantee = children[1]->is_syntactic_guarantee(); - is_.syntactic_persistence = children[1]->is_syntactic_persistence(); - if (children[0]->is_finite()) - { - is_.syntactic_safety = children[1]->is_syntactic_safety(); - is_.syntactic_obligation = children[1]->is_syntactic_obligation(); - is_.syntactic_recurrence = children[1]->is_syntactic_recurrence(); - } - else - { - is_.syntactic_safety = false; - is_.syntactic_obligation = children[1]->is_syntactic_guarantee(); - is_.syntactic_recurrence = children[1]->is_syntactic_guarantee(); - } - assert(children[0]->is_sere_formula()); - assert(children[1]->is_psl_formula()); - if (children[0]->is_boolean()) - is_.syntactic_si = false; - break; + is_.syntactic_guarantee = children[1]->is_syntactic_guarantee(); + is_.syntactic_persistence = children[1]->is_syntactic_persistence(); + if (children[0]->is_finite()) + { + is_.syntactic_safety = children[1]->is_syntactic_safety(); + is_.syntactic_obligation = children[1]->is_syntactic_obligation(); + is_.syntactic_recurrence = children[1]->is_syntactic_recurrence(); + } + else + { + is_.syntactic_safety = false; + is_.syntactic_obligation = children[1]->is_syntactic_guarantee(); + is_.syntactic_recurrence = children[1]->is_syntactic_guarantee(); + } + assert(children[0]->is_sere_formula()); + assert(children[1]->is_psl_formula()); + if (children[0]->is_boolean()) + is_.syntactic_si = false; + break; case op::UConcat: - props = children[0]->props & children[1]->props; - is_.not_marked = true; - is_.ltl_formula = false; - is_.boolean = false; - is_.sere_formula = false; - is_.accepting_eword = false; - is_.psl_formula = true; + props = children[0]->props & children[1]->props; + is_.not_marked = true; + is_.ltl_formula = false; + is_.boolean = false; + is_.sere_formula = false; + is_.accepting_eword = false; + is_.psl_formula = true; - is_.syntactic_safety = children[1]->is_syntactic_safety(); - is_.syntactic_recurrence = children[1]->is_syntactic_recurrence(); - if (children[0]->is_finite()) - { - is_.syntactic_guarantee = children[1]->is_syntactic_guarantee(); - is_.syntactic_obligation = children[1]->is_syntactic_obligation(); - is_.syntactic_persistence = - children[1]->is_syntactic_persistence(); - } - else - { - is_.syntactic_guarantee = false; - is_.syntactic_obligation = children[1]->is_syntactic_safety(); - is_.syntactic_persistence = children[1]->is_syntactic_safety(); - } - assert(children[0]->is_sere_formula()); - assert(children[1]->is_psl_formula()); - if (children[0]->is_boolean()) - is_.syntactic_si = false; - break; + is_.syntactic_safety = children[1]->is_syntactic_safety(); + is_.syntactic_recurrence = children[1]->is_syntactic_recurrence(); + if (children[0]->is_finite()) + { + is_.syntactic_guarantee = children[1]->is_syntactic_guarantee(); + is_.syntactic_obligation = children[1]->is_syntactic_obligation(); + is_.syntactic_persistence = + children[1]->is_syntactic_persistence(); + } + else + { + is_.syntactic_guarantee = false; + is_.syntactic_obligation = children[1]->is_syntactic_safety(); + is_.syntactic_persistence = children[1]->is_syntactic_safety(); + } + assert(children[0]->is_sere_formula()); + assert(children[1]->is_psl_formula()); + if (children[0]->is_boolean()) + is_.syntactic_si = false; + break; case op::U: - // Beware: (f U g) is a pure eventuality if both operands - // are pure eventualities, unlike in the proceedings of - // Concur'00. (The revision of the paper available at - // http://www.bell-labs.com/project/TMP/ is fixed.) See - // also http://arxiv.org/abs/1011.4214v2 for a discussion - // about this problem. (Which we fixed in 2005 thanks - // to LBTT.) - // This means that we can use the following line to handle - // all cases of (f U g), (f R g), (f W g), (f M g) for - // universality and eventuality. - props = children[0]->props & children[1]->props; - // The matter can be further refined because: - // (f U g) is a pure eventuality if - // g is a pure eventuality (regardless of f), - // or f == 1 - // (g M f) is a pure eventuality if f and g are, - // or f == 1 - // (g R f) is purely universal if - // f is purely universal (regardless of g) - // or g == 0 - // (f W g) is purely universal if f and g are - // or g == 0 - is_.not_marked = true; - // f U g is universal if g is eventual, or if f == 1. - is_.eventual = children[1]->is_eventual(); - is_.eventual |= children[0]->is_tt(); - is_.boolean = false; - is_.sere_formula = false; - is_.finite = false; - is_.accepting_eword = false; + // Beware: (f U g) is a pure eventuality if both operands + // are pure eventualities, unlike in the proceedings of + // Concur'00. (The revision of the paper available at + // http://www.bell-labs.com/project/TMP/ is fixed.) See + // also http://arxiv.org/abs/1011.4214v2 for a discussion + // about this problem. (Which we fixed in 2005 thanks + // to LBTT.) + // This means that we can use the following line to handle + // all cases of (f U g), (f R g), (f W g), (f M g) for + // universality and eventuality. + props = children[0]->props & children[1]->props; + // The matter can be further refined because: + // (f U g) is a pure eventuality if + // g is a pure eventuality (regardless of f), + // or f == 1 + // (g M f) is a pure eventuality if f and g are, + // or f == 1 + // (g R f) is purely universal if + // f is purely universal (regardless of g) + // or g == 0 + // (f W g) is purely universal if f and g are + // or g == 0 + is_.not_marked = true; + // f U g is universal if g is eventual, or if f == 1. + is_.eventual = children[1]->is_eventual(); + is_.eventual |= children[0]->is_tt(); + is_.boolean = false; + is_.sere_formula = false; + is_.finite = false; + is_.accepting_eword = false; - is_.syntactic_safety = false; - // is_.syntactic_guarantee = Guarantee U Guarantee - is_.syntactic_obligation = // Obligation U Guarantee - children[0]->is_syntactic_obligation() - && children[1]->is_syntactic_guarantee(); - is_.syntactic_recurrence = // Recurrence U Guarantee - children[0]->is_syntactic_recurrence() - && children[1]->is_syntactic_guarantee(); - // is_.syntactic_persistence = Persistence U Persistance - break; + is_.syntactic_safety = false; + // is_.syntactic_guarantee = Guarantee U Guarantee + is_.syntactic_obligation = // Obligation U Guarantee + children[0]->is_syntactic_obligation() + && children[1]->is_syntactic_guarantee(); + is_.syntactic_recurrence = // Recurrence U Guarantee + children[0]->is_syntactic_recurrence() + && children[1]->is_syntactic_guarantee(); + // is_.syntactic_persistence = Persistence U Persistance + break; case op::W: - // See comment for op::U. - props = children[0]->props & children[1]->props; - is_.not_marked = true; - // f W g is universal if f and g are, or if g == 0. - is_.universal |= children[1]->is_ff(); - is_.boolean = false; - is_.sere_formula = false; - is_.finite = false; - is_.accepting_eword = false; + // See comment for op::U. + props = children[0]->props & children[1]->props; + is_.not_marked = true; + // f W g is universal if f and g are, or if g == 0. + is_.universal |= children[1]->is_ff(); + is_.boolean = false; + is_.sere_formula = false; + is_.finite = false; + is_.accepting_eword = false; - // is_.syntactic_safety = Safety W Safety; - is_.syntactic_guarantee = false; - is_.syntactic_obligation = // Safety W Obligation - children[0]->is_syntactic_safety() - && children[1]->is_syntactic_obligation(); - // is_.syntactic_recurrence = Recurrence W Recurrence - is_.syntactic_persistence = // Safety W Persistance - children[0]->is_syntactic_safety() - && children[1]->is_syntactic_persistence(); + // is_.syntactic_safety = Safety W Safety; + is_.syntactic_guarantee = false; + is_.syntactic_obligation = // Safety W Obligation + children[0]->is_syntactic_safety() + && children[1]->is_syntactic_obligation(); + // is_.syntactic_recurrence = Recurrence W Recurrence + is_.syntactic_persistence = // Safety W Persistance + children[0]->is_syntactic_safety() + && children[1]->is_syntactic_persistence(); - break; + break; case op::R: - // See comment for op::U. - props = children[0]->props & children[1]->props; - is_.not_marked = true; - // g R f is universal if f is universal, or if g == 0. - is_.universal = children[1]->is_universal(); - is_.universal |= children[0]->is_ff(); - is_.boolean = false; - is_.sere_formula = false; - is_.finite = false; - is_.accepting_eword = false; + // See comment for op::U. + props = children[0]->props & children[1]->props; + is_.not_marked = true; + // g R f is universal if f is universal, or if g == 0. + is_.universal = children[1]->is_universal(); + is_.universal |= children[0]->is_ff(); + is_.boolean = false; + is_.sere_formula = false; + is_.finite = false; + is_.accepting_eword = false; - // is_.syntactic_safety = Safety R Safety; - is_.syntactic_guarantee = false; - is_.syntactic_obligation = // Obligation R Safety - children[0]->is_syntactic_obligation() - && children[1]->is_syntactic_safety(); - //is_.syntactic_recurrence = Recurrence R Recurrence - is_.syntactic_persistence = // Persistence R Safety - children[0]->is_syntactic_persistence() - && children[1]->is_syntactic_safety(); + // is_.syntactic_safety = Safety R Safety; + is_.syntactic_guarantee = false; + is_.syntactic_obligation = // Obligation R Safety + children[0]->is_syntactic_obligation() + && children[1]->is_syntactic_safety(); + //is_.syntactic_recurrence = Recurrence R Recurrence + is_.syntactic_persistence = // Persistence R Safety + children[0]->is_syntactic_persistence() + && children[1]->is_syntactic_safety(); - break; + break; case op::M: - // See comment for op::U. - props = children[0]->props & children[1]->props; - is_.not_marked = true; - // g M f is eventual if both g and f are eventual, or if f == 1. - is_.eventual |= children[1]->is_tt(); - is_.boolean = false; - is_.sere_formula = false; - is_.finite = false; - is_.accepting_eword = false; + // See comment for op::U. + props = children[0]->props & children[1]->props; + is_.not_marked = true; + // g M f is eventual if both g and f are eventual, or if f == 1. + is_.eventual |= children[1]->is_tt(); + is_.boolean = false; + is_.sere_formula = false; + is_.finite = false; + is_.accepting_eword = false; - is_.syntactic_safety = false; - // is_.syntactic_guarantee = Guarantee M Guarantee - is_.syntactic_obligation = // Guarantee M Obligation - children[0]->is_syntactic_guarantee() - && children[1]->is_syntactic_obligation(); - is_.syntactic_recurrence = // Guarantee M Recurrence - children[0]->is_syntactic_guarantee() - && children[1]->is_syntactic_recurrence(); - // is_.syntactic_persistence = Persistence M Persistance + is_.syntactic_safety = false; + // is_.syntactic_guarantee = Guarantee M Guarantee + is_.syntactic_obligation = // Guarantee M Obligation + children[0]->is_syntactic_guarantee() + && children[1]->is_syntactic_obligation(); + is_.syntactic_recurrence = // Guarantee M Recurrence + children[0]->is_syntactic_guarantee() + && children[1]->is_syntactic_recurrence(); + // is_.syntactic_persistence = Persistence M Persistance - break; + break; case op::Or: - { - props = children[0]->props; - unsigned s = size_; - bool ew = children[0]->accepts_eword(); - for (unsigned i = 1; i < s; ++i) - { - ew |= children[i]->accepts_eword(); - props &= children[i]->props; - } - is_.accepting_eword = ew; - break; - } + { + props = children[0]->props; + unsigned s = size_; + bool ew = children[0]->accepts_eword(); + for (unsigned i = 1; i < s; ++i) + { + ew |= children[i]->accepts_eword(); + props &= children[i]->props; + } + is_.accepting_eword = ew; + break; + } case op::OrRat: - { - props = children[0]->props; - unsigned s = size_; - bool syntactic_si = is_.syntactic_si && !is_.boolean; - // Note: OrRat(p1,p2) is a Boolean formula, but its is - // actually rewritten as Or(p1,p2) by trivial identities - // before this constructor is called. So at this point, - // AndNLM is always used with at most one Boolean argument, - // and the result is therefore NOT Boolean. - is_.boolean = false; - is_.ltl_formula = false; - is_.psl_formula = false; - is_.eventual = false; - is_.universal = false; + { + props = children[0]->props; + unsigned s = size_; + bool syntactic_si = is_.syntactic_si && !is_.boolean; + // Note: OrRat(p1,p2) is a Boolean formula, but its is + // actually rewritten as Or(p1,p2) by trivial identities + // before this constructor is called. So at this point, + // AndNLM is always used with at most one Boolean argument, + // and the result is therefore NOT Boolean. + is_.boolean = false; + is_.ltl_formula = false; + is_.psl_formula = false; + is_.eventual = false; + is_.universal = false; - bool ew = children[0]->accepts_eword(); - for (unsigned i = 1; i < s; ++i) - { - ew |= children[i]->accepts_eword(); - syntactic_si &= children[i]->is_syntactic_stutter_invariant() - && !children[i]->is_boolean(); - props &= children[i]->props; - } - is_.accepting_eword = ew; - is_.syntactic_si = syntactic_si; - break; - } + bool ew = children[0]->accepts_eword(); + for (unsigned i = 1; i < s; ++i) + { + ew |= children[i]->accepts_eword(); + syntactic_si &= children[i]->is_syntactic_stutter_invariant() + && !children[i]->is_boolean(); + props &= children[i]->props; + } + is_.accepting_eword = ew; + is_.syntactic_si = syntactic_si; + break; + } case op::And: - { - props = children[0]->props; - unsigned s = size_; - for (unsigned i = 1; i < s; ++i) - props &= children[i]->props; - break; - } + { + props = children[0]->props; + unsigned s = size_; + for (unsigned i = 1; i < s; ++i) + props &= children[i]->props; + break; + } case op::Fusion: case op::Concat: case op::AndNLM: case op::AndRat: - { - props = children[0]->props; - unsigned s = size_; - bool syntactic_si = is_.syntactic_si && !is_.boolean; - // Note: AndNLM(p1,p2) and AndRat(p1,p2) are Boolean - // formulae, but they are actually rewritten as And(p1,p2) - // by trivial identities before this constructor is called. - // So at this point, AndNLM/AndRat are always used with at - // most one Boolean argument, and the result is therefore - // NOT Boolean. - is_.boolean = false; - is_.ltl_formula = false; - is_.psl_formula = false; - is_.eventual = false; - is_.universal = false; + { + props = children[0]->props; + unsigned s = size_; + bool syntactic_si = is_.syntactic_si && !is_.boolean; + // Note: AndNLM(p1,p2) and AndRat(p1,p2) are Boolean + // formulae, but they are actually rewritten as And(p1,p2) + // by trivial identities before this constructor is called. + // So at this point, AndNLM/AndRat are always used with at + // most one Boolean argument, and the result is therefore + // NOT Boolean. + is_.boolean = false; + is_.ltl_formula = false; + is_.psl_formula = false; + is_.eventual = false; + is_.universal = false; - for (unsigned i = 1; i < s; ++i) - { - syntactic_si &= children[i]->is_syntactic_stutter_invariant() - && !children[i]->is_boolean(); - props &= children[i]->props; - } - is_.syntactic_si = syntactic_si; - if (op_ == op::Fusion) - is_.accepting_eword = false; - // A concatenation is an siSERE if it contains one stared - // Boolean, and the other operands are siSERE (i.e., - // sub-formulas that verify is_syntactic_stutter_invariant() and - // !is_boolean()); - if (op_ == op::Concat) - { - unsigned sb = 0; // stared Boolean formulas seen - for (unsigned i = 0; i < s; ++i) - { - auto ci = children[i]; - if (ci->is_syntactic_stutter_invariant() - && !ci->is_boolean()) - continue; - if (ci->is(op::Star)) - { - sb += ci->nth(0)->is_boolean(); - if (sb > 1) - break; - } - else - { - sb = 0; - break; - } - } - is_.syntactic_si = sb == 1; - } - break; - } + for (unsigned i = 1; i < s; ++i) + { + syntactic_si &= children[i]->is_syntactic_stutter_invariant() + && !children[i]->is_boolean(); + props &= children[i]->props; + } + is_.syntactic_si = syntactic_si; + if (op_ == op::Fusion) + is_.accepting_eword = false; + // A concatenation is an siSERE if it contains one stared + // Boolean, and the other operands are siSERE (i.e., + // sub-formulas that verify is_syntactic_stutter_invariant() and + // !is_boolean()); + if (op_ == op::Concat) + { + unsigned sb = 0; // stared Boolean formulas seen + for (unsigned i = 0; i < s; ++i) + { + auto ci = children[i]; + if (ci->is_syntactic_stutter_invariant() + && !ci->is_boolean()) + continue; + if (ci->is(op::Star)) + { + sb += ci->nth(0)->is_boolean(); + if (sb > 1) + break; + } + else + { + sb = 0; + break; + } + } + is_.syntactic_si = sb == 1; + } + break; + } case op::Star: case op::FStar: - { - props = children[0]->props; - assert(is_.sere_formula); - is_.boolean = false; - is_.ltl_formula = false; - is_.psl_formula = false; - is_.eventual = false; - is_.universal = false; - is_.syntactic_safety = false; - is_.syntactic_guarantee = false; - is_.syntactic_obligation = false; - is_.syntactic_recurrence = false; - is_.syntactic_persistence = false; + { + props = children[0]->props; + assert(is_.sere_formula); + is_.boolean = false; + is_.ltl_formula = false; + is_.psl_formula = false; + is_.eventual = false; + is_.universal = false; + is_.syntactic_safety = false; + is_.syntactic_guarantee = false; + is_.syntactic_obligation = false; + is_.syntactic_recurrence = false; + is_.syntactic_persistence = false; - switch (op_) - { - case op::Star: - if (max_ == unbounded()) - { - is_.finite = false; - is_.syntactic_si = min_ == 1 && children[0]->is_boolean(); - } - else - { - is_.syntactic_si = false; - } - if (min_ == 0) - is_.accepting_eword = true; - break; - case op::FStar: - is_.accepting_eword = false; - is_.syntactic_si &= !children[0]->is_boolean(); - if (max_ == unbounded()) - is_.finite = false; - if (min_ == 0) - is_.syntactic_si = false; - break; - default: - SPOT_UNREACHABLE(); - } - } - break; + switch (op_) + { + case op::Star: + if (max_ == unbounded()) + { + is_.finite = false; + is_.syntactic_si = min_ == 1 && children[0]->is_boolean(); + } + else + { + is_.syntactic_si = false; + } + if (min_ == 0) + is_.accepting_eword = true; + break; + case op::FStar: + is_.accepting_eword = false; + is_.syntactic_si &= !children[0]->is_boolean(); + if (max_ == unbounded()) + is_.finite = false; + if (min_ == 0) + is_.syntactic_si = false; + break; + default: + SPOT_UNREACHABLE(); + } + } + break; } } @@ -1583,23 +1583,23 @@ namespace spot os << kindstr() << "(@" << id_ << " #" << refs_; if (op_ == op::Star || op_ == op::FStar) { - os << ' ' << +min() << ".."; - auto m = max(); - if (m != unbounded()) - os << +m; + os << ' ' << +min() << ".."; + auto m = max(); + if (m != unbounded()) + os << +m; } if (op_ == op::ap) os << " \"" << ap_name() << '"'; if (auto s = size()) { - os << " ["; - for (auto c: *this) - { - c->dump(os); - if (--s) - os << ", "; - } - os << ']'; + os << " ["; + for (auto c: *this) + { + c->dump(os); + if (--s) + os << ", "; + } + os << ']'; } return os << ')'; } @@ -1615,19 +1615,19 @@ namespace spot case op::AndNLM: case op::Concat: case op::Fusion: - { - unsigned s = size(); - assert(s > 1); - vec v; - v.reserve(s - 1); - for (unsigned j = 0; j < s; ++j) - if (i != j) - v.push_back(nth(j)->clone()); - return multop(o, v); - } + { + unsigned s = size(); + assert(s > 1); + vec v; + v.reserve(s - 1); + for (unsigned j = 0; j < s; ++j) + if (i != j) + v.push_back(nth(j)->clone()); + return multop(o, v); + } default: - throw - std::runtime_error("all_but() is incompatible with this operator"); + throw + std::runtime_error("all_but() is incompatible with this operator"); } SPOT_UNREACHABLE(); } @@ -1652,11 +1652,11 @@ namespace spot unsigned cnt = 0; for (auto i: m.uniq) if (i->id() > 3 && i != one_star_) - { - if (!cnt++) - std::cerr << "*** m.uniq is not empty ***\n"; - i->dump(std::cerr) << std::endl; - } + { + if (!cnt++) + std::cerr << "*** m.uniq is not empty ***\n"; + i->dump(std::cerr) << std::endl; + } return cnt == 0; } @@ -1664,7 +1664,7 @@ namespace spot { if (!b.is_boolean()) throw - std::runtime_error("sugar_goto() called with non-Boolean argument"); + std::runtime_error("sugar_goto() called with non-Boolean argument"); // b[->min..max] is implemented as ((!b)[*];b)[*min..max] return Star(Concat({Star(Not(b)), b}), min, max); } @@ -1673,7 +1673,7 @@ namespace spot { if (!b.is_boolean()) throw - std::runtime_error("sugar_equal() called with non-Boolean argument"); + std::runtime_error("sugar_equal() called with non-Boolean argument"); // b[=0..] = 1[*] if (min == 0 && max == unbounded()) @@ -1689,38 +1689,38 @@ namespace spot return strverscmp(f->ap_name().c_str(), g->ap_name().c_str()); } -#define printprops \ - proprint(is_boolean, "B", "Boolean formula"); \ - proprint(is_sugar_free_boolean, "&", "without Boolean sugar"); \ - proprint(is_in_nenoform, "!", "in negative normal form"); \ - proprint(is_syntactic_stutter_invariant, "x", \ - "syntactic stutter invariant"); \ - proprint(is_sugar_free_ltl, "f", "without LTL sugar"); \ - proprint(is_ltl_formula, "L", "LTL formula"); \ - proprint(is_psl_formula, "P", "PSL formula"); \ - proprint(is_sere_formula, "S", "SERE formula"); \ - proprint(is_finite, "F", "finite"); \ - proprint(is_eventual, "e", "pure eventuality"); \ - proprint(is_universal, "u", "purely universal"); \ - proprint(is_syntactic_safety, "s", "syntactic safety"); \ - proprint(is_syntactic_guarantee, "g", "syntactic guarantee"); \ - proprint(is_syntactic_obligation, "o", "syntactic obligation"); \ - proprint(is_syntactic_persistence, "p", "syntactic persistence"); \ - proprint(is_syntactic_recurrence, "r", "syntactic recurrence"); \ - proprint(is_marked, "+", "marked"); \ - proprint(accepts_eword, "0", "accepts the empty word"); \ - proprint(has_lbt_atomic_props, "l", \ - "has LBT-style atomic props"); \ - proprint(has_spin_atomic_props, "a", \ - "has Spin-style atomic props"); +#define printprops \ + proprint(is_boolean, "B", "Boolean formula"); \ + proprint(is_sugar_free_boolean, "&", "without Boolean sugar"); \ + proprint(is_in_nenoform, "!", "in negative normal form"); \ + proprint(is_syntactic_stutter_invariant, "x", \ + "syntactic stutter invariant"); \ + proprint(is_sugar_free_ltl, "f", "without LTL sugar"); \ + proprint(is_ltl_formula, "L", "LTL formula"); \ + proprint(is_psl_formula, "P", "PSL formula"); \ + proprint(is_sere_formula, "S", "SERE formula"); \ + proprint(is_finite, "F", "finite"); \ + proprint(is_eventual, "e", "pure eventuality"); \ + proprint(is_universal, "u", "purely universal"); \ + proprint(is_syntactic_safety, "s", "syntactic safety"); \ + proprint(is_syntactic_guarantee, "g", "syntactic guarantee"); \ + proprint(is_syntactic_obligation, "o", "syntactic obligation"); \ + proprint(is_syntactic_persistence, "p", "syntactic persistence"); \ + proprint(is_syntactic_recurrence, "r", "syntactic recurrence"); \ + proprint(is_marked, "+", "marked"); \ + proprint(accepts_eword, "0", "accepts the empty word"); \ + proprint(has_lbt_atomic_props, "l", \ + "has LBT-style atomic props"); \ + proprint(has_spin_atomic_props, "a", \ + "has Spin-style atomic props"); std::list list_formula_props(const formula& f) { std::list res; -#define proprint(m, a, l) \ - if (f.m()) \ +#define proprint(m, a, l) \ + if (f.m()) \ res.emplace_back(l); printprops; #undef proprint @@ -1733,11 +1733,11 @@ namespace spot const char* comma = abbr ? "" : ", "; const char* sep = ""; -#define proprint(m, a, l) \ - if (f.m()) \ - { \ - out << sep; out << (abbr ? a : l); \ - sep = comma; \ +#define proprint(m, a, l) \ + if (f.m()) \ + { \ + out << sep; out << (abbr ? a : l); \ + sep = comma; \ } printprops; #undef proprint diff --git a/spot/tl/formula.hh b/spot/tl/formula.hh index 2b7e9013c..ad20fe202 100644 --- a/spot/tl/formula.hh +++ b/spot/tl/formula.hh @@ -61,41 +61,41 @@ namespace spot /// \brief Operator types enum class op: uint8_t { - ff, ///< False - tt, ///< True - eword, ///< Empty word - ap, ///< Atomic proposition + ff, ///< False + tt, ///< True + eword, ///< Empty word + ap, ///< Atomic proposition // unary operators - Not, ///< Negation - X, ///< Next - F, ///< Eventually - G, ///< Globally - Closure, ///< PSL Closure - NegClosure, ///< Negated PSL Closure - NegClosureMarked, ///< marked version of the Negated PSL Clusure + Not, ///< Negation + X, ///< Next + F, ///< Eventually + G, ///< Globally + Closure, ///< PSL Closure + NegClosure, ///< Negated PSL Closure + NegClosureMarked, ///< marked version of the Negated PSL Clusure // binary operators - Xor, ///< Exclusive Or - Implies, ///< Implication - Equiv, ///< Equivalence - U, ///< until - R, ///< release (dual of until) - W, ///< weak until - M, ///< strong release (dual of weak until) - EConcat, ///< Seq - EConcatMarked, ///< Seq, Marked - UConcat, ///< Triggers + Xor, ///< Exclusive Or + Implies, ///< Implication + Equiv, ///< Equivalence + U, ///< until + R, ///< release (dual of until) + W, ///< weak until + M, ///< strong release (dual of weak until) + EConcat, ///< Seq + EConcatMarked, ///< Seq, Marked + UConcat, ///< Triggers // n-ary operators - Or, ///< (omega-Rational) Or - OrRat, ///< Rational Or - And, ///< (omega-Rational) And - AndRat, ///< Rational And - AndNLM, ///< Non-Length-Matching Rational-And - Concat, ///< Concatenation - Fusion, ///< Fusion + Or, ///< (omega-Rational) Or + OrRat, ///< Rational Or + And, ///< (omega-Rational) And + AndRat, ///< Rational And + AndNLM, ///< Non-Length-Matching Rational-And + Concat, ///< Concatenation + Fusion, ///< Fusion // star-like operators - Star, ///< Star - FStar, ///< Fustion Star - }; + Star, ///< Star + FStar, ///< Fustion Star + }; #ifndef SWIG /// \brief Actual storage for formula nodes. @@ -106,469 +106,469 @@ namespace spot /// methods are documented there, rather than here. class SPOT_API fnode final { - public: - const fnode* clone() const - { - // Saturate. - ++refs_; - if (SPOT_UNLIKELY(!refs_)) - saturated_ = 1; - return this; - } + public: + const fnode* clone() const + { + // Saturate. + ++refs_; + if (SPOT_UNLIKELY(!refs_)) + saturated_ = 1; + return this; + } - void destroy() const - { - if (SPOT_LIKELY(refs_)) - --refs_; - else if (SPOT_LIKELY(id_ > 2) && SPOT_LIKELY(!saturated_)) - // last reference to a node that is not a constant - destroy_aux(); - } + void destroy() const + { + if (SPOT_LIKELY(refs_)) + --refs_; + else if (SPOT_LIKELY(id_ > 2) && SPOT_LIKELY(!saturated_)) + // last reference to a node that is not a constant + destroy_aux(); + } - static constexpr uint8_t unbounded() - { - return UINT8_MAX; - } + static constexpr uint8_t unbounded() + { + return UINT8_MAX; + } - static const fnode* ap(const std::string& name); - static const fnode* unop(op o, const fnode* f); - static const fnode* binop(op o, const fnode* f, const fnode* g); - static const fnode* multop(op o, std::vector l); - static const fnode* bunop(op o, const fnode* f, - uint8_t min, uint8_t max = unbounded()); + static const fnode* ap(const std::string& name); + static const fnode* unop(op o, const fnode* f); + static const fnode* binop(op o, const fnode* f, const fnode* g); + static const fnode* multop(op o, std::vector l); + static const fnode* bunop(op o, const fnode* f, + uint8_t min, uint8_t max = unbounded()); - op kind() const - { - return op_; - } + op kind() const + { + return op_; + } - std::string kindstr() const; + std::string kindstr() const; - bool is(op o) const - { - return op_ == o; - } + bool is(op o) const + { + return op_ == o; + } - bool is(op o1, op o2) const - { - return op_ == o1 || op_ == o2; - } + bool is(op o1, op o2) const + { + return op_ == o1 || op_ == o2; + } - bool is(std::initializer_list l) const - { - const fnode* n = this; - for (auto o: l) - { - if (!n->is(o)) - return false; - n = n->nth(0); - } - return true; - } + bool is(std::initializer_list l) const + { + const fnode* n = this; + for (auto o: l) + { + if (!n->is(o)) + return false; + n = n->nth(0); + } + return true; + } - const fnode* get_child_of(op o) const - { - if (op_ != o) - return nullptr; - assert(size_ == 1); - return nth(0); - } + const fnode* get_child_of(op o) const + { + if (op_ != o) + return nullptr; + assert(size_ == 1); + return nth(0); + } - const fnode* get_child_of(std::initializer_list l) const - { - auto c = this; - for (auto o: l) - { - c = c->get_child_of(o); - if (c == nullptr) - return c; - } - return c; - } + const fnode* get_child_of(std::initializer_list l) const + { + auto c = this; + for (auto o: l) + { + c = c->get_child_of(o); + if (c == nullptr) + return c; + } + return c; + } - unsigned min() const - { - assert(op_ == op::FStar || op_ == op::Star); - return min_; - } + unsigned min() const + { + assert(op_ == op::FStar || op_ == op::Star); + return min_; + } - unsigned max() const - { - assert(op_ == op::FStar || op_ == op::Star); - return max_; - } + unsigned max() const + { + assert(op_ == op::FStar || op_ == op::Star); + return max_; + } - unsigned size() const - { - return size_; - } + unsigned size() const + { + return size_; + } - size_t id() const - { - return id_; - } + size_t id() const + { + return id_; + } - const fnode*const* begin() const - { - return children; - } + const fnode*const* begin() const + { + return children; + } - const fnode*const* end() const - { - return children + size(); - } + const fnode*const* end() const + { + return children + size(); + } - const fnode* nth(unsigned i) const - { - if (i >= size()) - throw std::runtime_error("access to non-existing child"); - return children[i]; - } + const fnode* nth(unsigned i) const + { + if (i >= size()) + throw std::runtime_error("access to non-existing child"); + return children[i]; + } - static const fnode* ff() - { - return ff_; - } + static const fnode* ff() + { + return ff_; + } - bool is_ff() const - { - return op_ == op::ff; - } + bool is_ff() const + { + return op_ == op::ff; + } - static const fnode* tt() - { - return tt_; - } + static const fnode* tt() + { + return tt_; + } - bool is_tt() const - { - return op_ == op::tt; - } + bool is_tt() const + { + return op_ == op::tt; + } - static const fnode* eword() - { - return ew_; - } + static const fnode* eword() + { + return ew_; + } - bool is_eword() const - { - return op_ == op::eword; - } + bool is_eword() const + { + return op_ == op::eword; + } - bool is_constant() const - { - return op_ == op::ff || op_ == op::tt || op_ == op::eword; - } + bool is_constant() const + { + return op_ == op::ff || op_ == op::tt || op_ == op::eword; + } - bool is_Kleene_star() const - { - if (op_ != op::Star) - return false; - return min_ == 0 && max_ == unbounded(); - } + bool is_Kleene_star() const + { + if (op_ != op::Star) + return false; + return min_ == 0 && max_ == unbounded(); + } - static const fnode* one_star() - { - if (!one_star_) - one_star_ = bunop(op::Star, tt(), 0); - return one_star_; - } + static const fnode* one_star() + { + if (!one_star_) + one_star_ = bunop(op::Star, tt(), 0); + return one_star_; + } - const std::string& ap_name() const; - std::ostream& dump(std::ostream& os) const; + const std::string& ap_name() const; + std::ostream& dump(std::ostream& os) const; - const fnode* all_but(unsigned i) const; + const fnode* all_but(unsigned i) const; - unsigned boolean_count() const - { - unsigned pos = 0; - unsigned s = size(); - while (pos < s && children[pos]->is_boolean()) - ++pos; - return pos; - } + unsigned boolean_count() const + { + unsigned pos = 0; + unsigned s = size(); + while (pos < s && children[pos]->is_boolean()) + ++pos; + return pos; + } - const fnode* boolean_operands(unsigned* width = nullptr) const; + const fnode* boolean_operands(unsigned* width = nullptr) const; - /// return true if the unicity map contains only the globally - /// pre-allocated formulas. - static bool instances_check(); + /// return true if the unicity map contains only the globally + /// pre-allocated formulas. + static bool instances_check(); - //////////////// - // Properties // - //////////////// + //////////////// + // Properties // + //////////////// - bool is_boolean() const - { - return is_.boolean; - } + bool is_boolean() const + { + return is_.boolean; + } - bool is_sugar_free_boolean() const - { - return is_.sugar_free_boolean; - } + bool is_sugar_free_boolean() const + { + return is_.sugar_free_boolean; + } - bool is_in_nenoform() const - { - return is_.in_nenoform; - } + bool is_in_nenoform() const + { + return is_.in_nenoform; + } - bool is_syntactic_stutter_invariant() const - { - return is_.syntactic_si; - } + bool is_syntactic_stutter_invariant() const + { + return is_.syntactic_si; + } - bool is_sugar_free_ltl() const - { - return is_.sugar_free_ltl; - } + bool is_sugar_free_ltl() const + { + return is_.sugar_free_ltl; + } - bool is_ltl_formula() const - { - return is_.ltl_formula; - } + bool is_ltl_formula() const + { + return is_.ltl_formula; + } - bool is_psl_formula() const - { - return is_.psl_formula; - } + bool is_psl_formula() const + { + return is_.psl_formula; + } - bool is_sere_formula() const - { - return is_.sere_formula; - } + bool is_sere_formula() const + { + return is_.sere_formula; + } - bool is_finite() const - { - return is_.finite; - } + bool is_finite() const + { + return is_.finite; + } - bool is_eventual() const - { - return is_.eventual; - } + bool is_eventual() const + { + return is_.eventual; + } - bool is_universal() const - { - return is_.universal; - } + bool is_universal() const + { + return is_.universal; + } - bool is_syntactic_safety() const - { - return is_.syntactic_safety; - } + bool is_syntactic_safety() const + { + return is_.syntactic_safety; + } - bool is_syntactic_guarantee() const - { - return is_.syntactic_guarantee; - } + bool is_syntactic_guarantee() const + { + return is_.syntactic_guarantee; + } - bool is_syntactic_obligation() const - { - return is_.syntactic_obligation; - } + bool is_syntactic_obligation() const + { + return is_.syntactic_obligation; + } - bool is_syntactic_recurrence() const - { - return is_.syntactic_recurrence; - } + bool is_syntactic_recurrence() const + { + return is_.syntactic_recurrence; + } - bool is_syntactic_persistence() const - { - return is_.syntactic_persistence; - } + bool is_syntactic_persistence() const + { + return is_.syntactic_persistence; + } - bool is_marked() const - { - return !is_.not_marked; - } + bool is_marked() const + { + return !is_.not_marked; + } - bool accepts_eword() const - { - return is_.accepting_eword; - } + bool accepts_eword() const + { + return is_.accepting_eword; + } - bool has_lbt_atomic_props() const - { - return is_.lbt_atomic_props; - } + bool has_lbt_atomic_props() const + { + return is_.lbt_atomic_props; + } - bool has_spin_atomic_props() const - { - return is_.spin_atomic_props; - } + bool has_spin_atomic_props() const + { + return is_.spin_atomic_props; + } - private: - void setup_props(op o); - void destroy_aux() const; + private: + void setup_props(op o); + void destroy_aux() const; - static const fnode* unique(const fnode*); + static const fnode* unique(const fnode*); - // Destruction may only happen via destroy(). - ~fnode() = default; - // Disallow copies. - fnode(const fnode&) = delete; - fnode& operator=(const fnode&) = delete; + // Destruction may only happen via destroy(). + ~fnode() = default; + // Disallow copies. + fnode(const fnode&) = delete; + fnode& operator=(const fnode&) = delete; - template - fnode(op o, iter begin, iter end) - { - size_t s = std::distance(begin, end); - if (s > (size_t) UINT16_MAX) - throw std::runtime_error("too many children for formula"); - size_ = s; - auto pos = children; - for (auto i = begin; i != end; ++i) - *pos++ = *i; - setup_props(o); - } + template + fnode(op o, iter begin, iter end) + { + size_t s = std::distance(begin, end); + if (s > (size_t) UINT16_MAX) + throw std::runtime_error("too many children for formula"); + size_ = s; + auto pos = children; + for (auto i = begin; i != end; ++i) + *pos++ = *i; + setup_props(o); + } - fnode(op o, std::initializer_list l) - : fnode(o, l.begin(), l.end()) + fnode(op o, std::initializer_list l) + : fnode(o, l.begin(), l.end()) { } - fnode(op o, const fnode* f, uint8_t min, uint8_t max) + fnode(op o, const fnode* f, uint8_t min, uint8_t max) { - size_ = 1; - children[0] = f; - min_ = min; - max_ = max; - setup_props(o); + size_ = 1; + children[0] = f; + min_ = min; + max_ = max; + setup_props(o); } - static const fnode* ff_; - static const fnode* tt_; - static const fnode* ew_; - static const fnode* one_star_; + static const fnode* ff_; + static const fnode* tt_; + static const fnode* ew_; + static const fnode* one_star_; - op op_; // operator - uint8_t min_; // range minimum (for star-like operators) - uint8_t max_; // range maximum; - mutable uint8_t saturated_ = 0; - uint16_t size_; // number of children - mutable uint16_t refs_ = 0; // reference count - 1; - size_t id_; // Also used as hash. - static size_t next_id_; + op op_; // operator + uint8_t min_; // range minimum (for star-like operators) + uint8_t max_; // range maximum; + mutable uint8_t saturated_ = 0; + uint16_t size_; // number of children + mutable uint16_t refs_ = 0; // reference count - 1; + size_t id_; // Also used as hash. + static size_t next_id_; - struct ltl_prop - { - // All properties here should be expressed in such a a way - // that property(f && g) is just property(f)&property(g). - // This allows us to compute all properties of a compound - // formula in one operation. - // - // For instance we do not use a property that says "has - // temporal operator", because it would require an OR between - // the two arguments. Instead we have a property that - // says "no temporal operator", and that one is computed - // with an AND between the arguments. - // - // Also choose a name that makes sense when prefixed with - // "the formula is". - bool boolean:1; // No temporal operators. - bool sugar_free_boolean:1; // Only AND, OR, and NOT operators. - bool in_nenoform:1; // Negative Normal Form. - bool syntactic_si:1; // LTL-X or siPSL - bool sugar_free_ltl:1; // No F and G operators. - bool ltl_formula:1; // Only LTL operators. - bool psl_formula:1; // Only PSL operators. - bool sere_formula:1; // Only SERE operators. - bool finite:1; // Finite SERE formulae, or Bool+X forms. - bool eventual:1; // Purely eventual formula. - bool universal:1; // Purely universal formula. - bool syntactic_safety:1; // Syntactic Safety Property. - bool syntactic_guarantee:1; // Syntactic Guarantee Property. - bool syntactic_obligation:1; // Syntactic Obligation Property. - bool syntactic_recurrence:1; // Syntactic Recurrence Property. - bool syntactic_persistence:1; // Syntactic Persistence Property. - bool not_marked:1; // No occurrence of EConcatMarked. - bool accepting_eword:1; // Accepts the empty word. - bool lbt_atomic_props:1; // Use only atomic propositions like p42. - bool spin_atomic_props:1; // Use only spin-compatible atomic props. - }; - union - { - // Use an unsigned for fast computation of all properties. - unsigned props; - ltl_prop is_; - }; + struct ltl_prop + { + // All properties here should be expressed in such a a way + // that property(f && g) is just property(f)&property(g). + // This allows us to compute all properties of a compound + // formula in one operation. + // + // For instance we do not use a property that says "has + // temporal operator", because it would require an OR between + // the two arguments. Instead we have a property that + // says "no temporal operator", and that one is computed + // with an AND between the arguments. + // + // Also choose a name that makes sense when prefixed with + // "the formula is". + bool boolean:1; // No temporal operators. + bool sugar_free_boolean:1; // Only AND, OR, and NOT operators. + bool in_nenoform:1; // Negative Normal Form. + bool syntactic_si:1; // LTL-X or siPSL + bool sugar_free_ltl:1; // No F and G operators. + bool ltl_formula:1; // Only LTL operators. + bool psl_formula:1; // Only PSL operators. + bool sere_formula:1; // Only SERE operators. + bool finite:1; // Finite SERE formulae, or Bool+X forms. + bool eventual:1; // Purely eventual formula. + bool universal:1; // Purely universal formula. + bool syntactic_safety:1; // Syntactic Safety Property. + bool syntactic_guarantee:1; // Syntactic Guarantee Property. + bool syntactic_obligation:1; // Syntactic Obligation Property. + bool syntactic_recurrence:1; // Syntactic Recurrence Property. + bool syntactic_persistence:1; // Syntactic Persistence Property. + bool not_marked:1; // No occurrence of EConcatMarked. + bool accepting_eword:1; // Accepts the empty word. + bool lbt_atomic_props:1; // Use only atomic propositions like p42. + bool spin_atomic_props:1; // Use only spin-compatible atomic props. + }; + union + { + // Use an unsigned for fast computation of all properties. + unsigned props; + ltl_prop is_; + }; - const fnode* children[1]; + const fnode* children[1]; }; /// Order two atomic propositions. SPOT_API - int atomic_prop_cmp(const fnode* f, const fnode* g); + int atomic_prop_cmp(const fnode* f, const fnode* g); struct formula_ptr_less_than_bool_first { bool - operator()(const fnode* left, const fnode* right) const - { - assert(left); - assert(right); - if (left == right) - return false; + operator()(const fnode* left, const fnode* right) const + { + assert(left); + assert(right); + if (left == right) + return false; - // We want Boolean formulae first. - bool lib = left->is_boolean(); - if (lib != right->is_boolean()) - return lib; + // We want Boolean formulae first. + bool lib = left->is_boolean(); + if (lib != right->is_boolean()) + return lib; - // We have two Boolean formulae - if (lib) - { - bool lconst = left->is_constant(); - if (lconst != right->is_constant()) - return lconst; - if (!lconst) - { - auto get_literal = [](const fnode* f) -> const fnode* - { - if (f->is(op::Not)) - f = f->nth(0); - if (f->is(op::ap)) - return f; - return nullptr; - }; - // Literals should come first - const fnode* litl = get_literal(left); - const fnode* litr = get_literal(right); - if (!litl != !litr) - return litl; - if (litl) - { - // And they should be sorted alphabetically - int cmp = atomic_prop_cmp(litl, litr); - if (cmp) - return cmp < 0; - } - } - } + // We have two Boolean formulae + if (lib) + { + bool lconst = left->is_constant(); + if (lconst != right->is_constant()) + return lconst; + if (!lconst) + { + auto get_literal = [](const fnode* f) -> const fnode* + { + if (f->is(op::Not)) + f = f->nth(0); + if (f->is(op::ap)) + return f; + return nullptr; + }; + // Literals should come first + const fnode* litl = get_literal(left); + const fnode* litr = get_literal(right); + if (!litl != !litr) + return litl; + if (litl) + { + // And they should be sorted alphabetically + int cmp = atomic_prop_cmp(litl, litr); + if (cmp) + return cmp < 0; + } + } + } - size_t l = left->id(); - size_t r = right->id(); - if (l != r) - return l < r; - // Because the hash code assigned to each formula is the - // number of formulae constructed so far, it is very unlikely - // that we will ever reach a case were two different formulae - // have the same hash. This will happen only ever with have - // produced 256**sizeof(size_t) formulae (i.e. max_count has - // looped back to 0 and started over). In that case we can - // order two formulas by looking at their text representation. - // We could be more efficient and look at their AST, but it's - // not worth the burden. (Also ordering pointers is ruled out - // because it breaks the determinism of the implementation.) - std::ostringstream old; - left->dump(old); - std::ostringstream ord; - right->dump(ord); - return old.str() < ord.str(); - } + size_t l = left->id(); + size_t r = right->id(); + if (l != r) + return l < r; + // Because the hash code assigned to each formula is the + // number of formulae constructed so far, it is very unlikely + // that we will ever reach a case were two different formulae + // have the same hash. This will happen only ever with have + // produced 256**sizeof(size_t) formulae (i.e. max_count has + // looped back to 0 and started over). In that case we can + // order two formulas by looking at their text representation. + // We could be more efficient and look at their AST, but it's + // not worth the burden. (Also ordering pointers is ruled out + // because it breaks the determinism of the implementation.) + std::ostringstream old; + left->dump(old); + std::ostringstream ord; + right->dump(ord); + return old.str() < ord.str(); + } }; #endif // SWIG @@ -578,11 +578,11 @@ namespace spot class SPOT_API formula final { const fnode* ptr_; - public: + public: explicit formula(const fnode* f) noexcept : ptr_(f) - { - } + { + } formula(std::nullptr_t) noexcept : ptr_(nullptr) @@ -597,53 +597,53 @@ namespace spot formula(const formula& f) noexcept : ptr_(f.ptr_) { - if (ptr_) - ptr_->clone(); + if (ptr_) + ptr_->clone(); } formula(formula&& f) noexcept : ptr_(f.ptr_) { - f.ptr_ = nullptr; + f.ptr_ = nullptr; } ~formula() - { - if (ptr_) - ptr_->destroy(); - } + { + if (ptr_) + ptr_->destroy(); + } const formula& operator=(std::nullptr_t) - { - this->~formula(); - ptr_ = nullptr; - return *this; - } + { + this->~formula(); + ptr_ = nullptr; + return *this; + } const formula& operator=(const formula& f) - { - this->~formula(); - if ((ptr_ = f.ptr_)) - ptr_->clone(); - return *this; - } + { + this->~formula(); + if ((ptr_ = f.ptr_)) + ptr_->clone(); + return *this; + } const formula& operator=(formula&& f) noexcept - { - std::swap(f.ptr_, ptr_); - return *this; - } + { + std::swap(f.ptr_, ptr_); + return *this; + } bool operator<(const formula& other) const noexcept { if (SPOT_UNLIKELY(!other.ptr_)) - return false; + return false; if (SPOT_UNLIKELY(!ptr_)) - return true; + return true; if (id() < other.id()) - return true; + return true; if (id() > other.id()) - return false; + return false; // The case where id()==other.id() but ptr_ != other.ptr_ is // very unlikely (we would need to build more that UINT_MAX // formulas), so let's just compare pointer, and ignore the fact @@ -725,20 +725,20 @@ namespace spot /// @} #ifdef SWIG -#define SPOT_DEF_UNOP(Name) \ - static formula Name(const formula& f) \ - { \ - return unop(op::Name, f); \ +#define SPOT_DEF_UNOP(Name) \ + static formula Name(const formula& f) \ + { \ + return unop(op::Name, f); \ } #else // !SWIG -#define SPOT_DEF_UNOP(Name) \ - static formula Name(const formula& f) \ - { \ - return unop(op::Name, f); \ - } \ - static formula Name(formula&& f) \ - { \ - return unop(op::Name, std::move(f)); \ +#define SPOT_DEF_UNOP(Name) \ + static formula Name(const formula& f) \ + { \ + return unop(op::Name, f); \ + } \ + static formula Name(formula&& f) \ + { \ + return unop(op::Name, std::move(f)); \ } #endif // !SWIG /// \brief Construct a negation @@ -804,28 +804,28 @@ namespace spot #endif //SWIG #ifdef SWIG -#define SPOT_DEF_BINOP(Name) \ - static formula Name(const formula& f, const formula& g) \ - { \ - return binop(op::Name, f, g); \ +#define SPOT_DEF_BINOP(Name) \ + static formula Name(const formula& f, const formula& g) \ + { \ + return binop(op::Name, f, g); \ } #else // !SWIG -#define SPOT_DEF_BINOP(Name) \ - static formula Name(const formula& f, const formula& g) \ - { \ - return binop(op::Name, f, g); \ - } \ - static formula Name(const formula& f, formula&& g) \ - { \ - return binop(op::Name, f, std::move(g)); \ - } \ - static formula Name(formula&& f, const formula& g) \ - { \ - return binop(op::Name, std::move(f), g); \ - } \ - static formula Name(formula&& f, formula&& g) \ - { \ - return binop(op::Name, std::move(f), std::move(g)); \ +#define SPOT_DEF_BINOP(Name) \ + static formula Name(const formula& f, const formula& g) \ + { \ + return binop(op::Name, f, g); \ + } \ + static formula Name(const formula& f, formula&& g) \ + { \ + return binop(op::Name, f, std::move(g)); \ + } \ + static formula Name(formula&& f, const formula& g) \ + { \ + return binop(op::Name, std::move(f), g); \ + } \ + static formula Name(formula&& f, formula&& g) \ + { \ + return binop(op::Name, std::move(f), std::move(g)); \ } #endif // !SWIG /// \brief Construct an Xor formula @@ -889,8 +889,8 @@ namespace spot std::vector tmp; tmp.reserve(l.size()); for (auto f: l) - if (f.ptr_) - tmp.push_back(f.ptr_->clone()); + if (f.ptr_) + tmp.push_back(f.ptr_->clone()); return formula(fnode::multop(o, std::move(tmp))); } @@ -900,29 +900,29 @@ namespace spot std::vector tmp; tmp.reserve(l.size()); for (auto f: l) - if (f.ptr_) - tmp.push_back(f.to_node_()); + if (f.ptr_) + tmp.push_back(f.to_node_()); return formula(fnode::multop(o, std::move(tmp))); } #endif // !SWIG /// @} #ifdef SWIG -#define SPOT_DEF_MULTOP(Name) \ - static formula Name(const std::vector& l) \ - { \ - return multop(op::Name, l); \ +#define SPOT_DEF_MULTOP(Name) \ + static formula Name(const std::vector& l) \ + { \ + return multop(op::Name, l); \ } #else // !SWIG -#define SPOT_DEF_MULTOP(Name) \ - static formula Name(const std::vector& l) \ - { \ - return multop(op::Name, l); \ - } \ - \ - static formula Name(std::vector&& l) \ - { \ - return multop(op::Name, std::move(l)); \ +#define SPOT_DEF_MULTOP(Name) \ + static formula Name(const std::vector& l) \ + { \ + return multop(op::Name, l); \ + } \ + \ + static formula Name(std::vector&& l) \ + { \ + return multop(op::Name, std::move(l)); \ } #endif // !SWIG /// \brief Construct an Or formula. @@ -966,16 +966,16 @@ namespace spot /// \pre \a o should be op::Star or op::FStar. /// @{ static formula bunop(op o, const formula& f, - uint8_t min = 0U, - uint8_t max = unbounded()) + uint8_t min = 0U, + uint8_t max = unbounded()) { return formula(fnode::bunop(o, f.ptr_->clone(), min, max)); } #ifndef SWIG static formula bunop(op o, formula&& f, - uint8_t min = 0U, - uint8_t max = unbounded()) + uint8_t min = 0U, + uint8_t max = unbounded()) { return formula(fnode::bunop(o, f.to_node_(), min, max)); } @@ -983,26 +983,26 @@ namespace spot ///@} #if SWIG -#define SPOT_DEF_BUNOP(Name) \ - static formula Name(const formula& f, \ - uint8_t min = 0U, \ - uint8_t max = unbounded()) \ - { \ - return bunop(op::Name, f, min, max); \ +#define SPOT_DEF_BUNOP(Name) \ + static formula Name(const formula& f, \ + uint8_t min = 0U, \ + uint8_t max = unbounded()) \ + { \ + return bunop(op::Name, f, min, max); \ } #else // !SWIG -#define SPOT_DEF_BUNOP(Name) \ - static formula Name(const formula& f, \ - uint8_t min = 0U, \ - uint8_t max = unbounded()) \ - { \ - return bunop(op::Name, f, min, max); \ - } \ - static formula Name(formula&& f, \ - uint8_t min = 0U, \ - uint8_t max = unbounded()) \ - { \ - return bunop(op::Name, std::move(f), min, max); \ +#define SPOT_DEF_BUNOP(Name) \ + static formula Name(const formula& f, \ + uint8_t min = 0U, \ + uint8_t max = unbounded()) \ + { \ + return bunop(op::Name, f, min, max); \ + } \ + static formula Name(formula&& f, \ + uint8_t min = 0U, \ + uint8_t max = unbounded()) \ + { \ + return bunop(op::Name, std::move(f), min, max); \ } #endif /// \brief Create SERE for f[*min..max] @@ -1015,20 +1015,20 @@ namespace spot /// This operator is a generalization of the (+) operator /// defined in the following paper. /** \verbatim - @InProceedings{ dax.09.atva, - author = {Christian Dax and Felix Klaedtke and Stefan Leue}, - title = {Specification Languages for Stutter-Invariant Regular - Properties}, - booktitle = {Proceedings of the 7th International Symposium on - Automated Technology for Verification and Analysis - (ATVA'09)}, - pages = {244--254}, - year = {2009}, - volume = {5799}, - series = {Lecture Notes in Computer Science}, - publisher = {Springer-Verlag} - } - \endverbatim */ + @InProceedings{ dax.09.atva, + author = {Christian Dax and Felix Klaedtke and Stefan Leue}, + title = {Specification Languages for Stutter-Invariant Regular + Properties}, + booktitle = {Proceedings of the 7th International Symposium on + Automated Technology for Verification and Analysis + (ATVA'09)}, + pages = {244--254}, + year = {2009}, + volume = {5799}, + series = {Lecture Notes in Computer Science}, + publisher = {Springer-Verlag} + } + \endverbatim */ /// @{ SPOT_DEF_BUNOP(FStar); /// @} @@ -1105,7 +1105,7 @@ namespace spot { auto f = ptr_->get_child_of(o); if (f) - f->clone(); + f->clone(); return formula(f); } @@ -1120,7 +1120,7 @@ namespace spot { auto f = ptr_->get_child_of(l); if (f) - f->clone(); + f->clone(); return formula(f); } #endif @@ -1165,43 +1165,43 @@ namespace spot class SPOT_API formula_child_iterator final { const fnode*const* ptr_; - public: + public: formula_child_iterator() - : ptr_(nullptr) - { - } + : ptr_(nullptr) + { + } formula_child_iterator(const fnode*const* f) - : ptr_(f) - { - } + : ptr_(f) + { + } bool operator==(formula_child_iterator o) { - return ptr_ == o.ptr_; + return ptr_ == o.ptr_; } bool operator!=(formula_child_iterator o) { - return ptr_ != o.ptr_; + return ptr_ != o.ptr_; } formula operator*() { - return formula((*ptr_)->clone()); + return formula((*ptr_)->clone()); } formula_child_iterator operator++() { - ++ptr_; - return *this; + ++ptr_; + return *this; } formula_child_iterator operator++(int) { - auto tmp = *this; - ++ptr_; - return tmp; + auto tmp = *this; + ++ptr_; + return tmp; } }; @@ -1286,10 +1286,10 @@ namespace spot bool is_literal() { return (is(op::ap) || - // If f is in nenoform, Not can only occur in front of - // an atomic proposition. So this way we do not have - // to check the type of the child. - (is(op::Not) && is_boolean() && is_in_nenoform())); + // If f is in nenoform, Not can only occur in front of + // an atomic proposition. So this way we do not have + // to check the type of the child. + (is(op::Not) && is_boolean() && is_in_nenoform())); } /// \brief Print the name of an atomic proposition. @@ -1351,10 +1351,10 @@ namespace spot return formula(ptr_->boolean_operands(width)); } -#define SPOT_DEF_PROP(Name) \ - bool Name() const \ - { \ - return ptr_->Name(); \ +#define SPOT_DEF_PROP(Name) \ + bool Name() const \ + { \ + return ptr_->Name(); \ } //////////////// // Properties // @@ -1386,19 +1386,19 @@ namespace spot /// /// Pure eventuality formulae are defined in /** \verbatim - @InProceedings{ etessami.00.concur, - author = {Kousha Etessami and Gerard J. Holzmann}, - title = {Optimizing {B\"u}chi Automata}, - booktitle = {Proceedings of the 11th International Conference on - Concurrency Theory (Concur'2000)}, - pages = {153--167}, - year = {2000}, - editor = {C. Palamidessi}, - volume = {1877}, - series = {Lecture Notes in Computer Science}, - publisher = {Springer-Verlag} - } - \endverbatim */ + @InProceedings{ etessami.00.concur, + author = {Kousha Etessami and Gerard J. Holzmann}, + title = {Optimizing {B\"u}chi Automata}, + booktitle = {Proceedings of the 11th International Conference on + Concurrency Theory (Concur'2000)}, + pages = {153--167}, + year = {2000}, + editor = {C. Palamidessi}, + volume = {1877}, + series = {Lecture Notes in Computer Science}, + publisher = {Springer-Verlag} + } + \endverbatim */ /// /// A word that satisfies a pure eventuality can be prefixed by /// anything and still satisfies the formula. @@ -1407,19 +1407,19 @@ namespace spot /// /// Purely universal formulae are defined in /** \verbatim - @InProceedings{ etessami.00.concur, - author = {Kousha Etessami and Gerard J. Holzmann}, - title = {Optimizing {B\"u}chi Automata}, - booktitle = {Proceedings of the 11th International Conference on - Concurrency Theory (Concur'2000)}, - pages = {153--167}, - year = {2000}, - editor = {C. Palamidessi}, - volume = {1877}, - series = {Lecture Notes in Computer Science}, - publisher = {Springer-Verlag} - } - \endverbatim */ + @InProceedings{ etessami.00.concur, + author = {Kousha Etessami and Gerard J. Holzmann}, + title = {Optimizing {B\"u}chi Automata}, + booktitle = {Proceedings of the 11th International Conference on + Concurrency Theory (Concur'2000)}, + pages = {153--167}, + year = {2000}, + editor = {C. Palamidessi}, + volume = {1877}, + series = {Lecture Notes in Computer Science}, + publisher = {Springer-Verlag} + } + \endverbatim */ /// /// Any (non-empty) suffix of a word that satisfies a purely /// universal formula also satisfies the formula. @@ -1459,56 +1459,56 @@ namespace spot /// \brief Clone this node after applying \a trans to its children. template formula map(Trans trans) - { - switch (op o = kind()) - { - case op::ff: - case op::tt: - case op::eword: - case op::ap: - return *this; - case op::Not: - case op::X: - case op::F: - case op::G: - case op::Closure: - case op::NegClosure: - case op::NegClosureMarked: - return unop(o, trans((*this)[0])); - case op::Xor: - case op::Implies: - case op::Equiv: - case op::U: - case op::R: - case op::W: - case op::M: - case op::EConcat: - case op::EConcatMarked: - case op::UConcat: - { - formula tmp = trans((*this)[0]); - return binop(o, tmp, trans((*this)[1])); - } - case op::Or: - case op::OrRat: - case op::And: - case op::AndRat: - case op::AndNLM: - case op::Concat: - case op::Fusion: - { - std::vector tmp; - tmp.reserve(size()); - for (auto f: *this) - tmp.push_back(trans(f)); - return multop(o, std::move(tmp)); - } - case op::Star: - case op::FStar: - return bunop(o, trans((*this)[0]), min(), max()); - } - SPOT_UNREACHABLE(); - } + { + switch (op o = kind()) + { + case op::ff: + case op::tt: + case op::eword: + case op::ap: + return *this; + case op::Not: + case op::X: + case op::F: + case op::G: + case op::Closure: + case op::NegClosure: + case op::NegClosureMarked: + return unop(o, trans((*this)[0])); + case op::Xor: + case op::Implies: + case op::Equiv: + case op::U: + case op::R: + case op::W: + case op::M: + case op::EConcat: + case op::EConcatMarked: + case op::UConcat: + { + formula tmp = trans((*this)[0]); + return binop(o, tmp, trans((*this)[1])); + } + case op::Or: + case op::OrRat: + case op::And: + case op::AndRat: + case op::AndNLM: + case op::Concat: + case op::Fusion: + { + std::vector tmp; + tmp.reserve(size()); + for (auto f: *this) + tmp.push_back(trans(f)); + return multop(o, std::move(tmp)); + } + case op::Star: + case op::FStar: + return bunop(o, trans((*this)[0]), min(), max()); + } + SPOT_UNREACHABLE(); + } /// \brief Apply \a func to each subformula. /// @@ -1517,38 +1517,38 @@ namespace spot /// current node are skipped. template void traverse(Func func) - { - if (func(*this)) - return; - for (auto f: *this) - f.traverse(func); - } + { + if (func(*this)) + return; + for (auto f: *this) + f.traverse(func); + } }; /// Print the properties of formula \a f on stream \a out. SPOT_API - std::ostream& print_formula_props(std::ostream& out, const formula& f, - bool abbreviated = false); + std::ostream& print_formula_props(std::ostream& out, const formula& f, + bool abbreviated = false); /// List the properties of formula \a f. SPOT_API - std::list list_formula_props(const formula& f); + std::list list_formula_props(const formula& f); /// Print a formula. SPOT_API - std::ostream& operator<<(std::ostream& os, const formula& f); + std::ostream& operator<<(std::ostream& os, const formula& f); } #ifndef SWIG namespace std { template <> - struct hash - { - size_t operator()(const spot::formula& x) const noexcept + struct hash { - return x.id(); - } - }; + size_t operator()(const spot::formula& x) const noexcept + { + return x.id(); + } + }; } #endif diff --git a/spot/tl/length.cc b/spot/tl/length.cc index 2c87a62e5..789df65b2 100644 --- a/spot/tl/length.cc +++ b/spot/tl/length.cc @@ -30,14 +30,14 @@ namespace spot { int len = 0; f.traverse([&len](const formula& x) - { - auto s = x.size(); - if (s > 1) - len += s - 1; - else - ++len; - return false; - }); + { + auto s = x.size(); + if (s > 1) + len += s - 1; + else + ++len; + return false; + }); return len; } @@ -46,31 +46,31 @@ namespace spot { int len = 0; f.traverse([&len](const formula& x) - { - if (x.is_boolean()) - { - ++len; - return true; - } - auto s = x.size(); - if (s > 2) - { - int b = 0; - for (const auto& y: x) - if (y.is_boolean()) - ++b; - len += s - b * 2 + 1; - } - else if (s > 1) - { - len += s - 1; - } - else - { - ++len; - } - return false; - }); + { + if (x.is_boolean()) + { + ++len; + return true; + } + auto s = x.size(); + if (s > 2) + { + int b = 0; + for (const auto& y: x) + if (y.is_boolean()) + ++b; + len += s - b * 2 + 1; + } + else if (s > 1) + { + len += s - 1; + } + else + { + ++len; + } + return false; + }); return len; } diff --git a/spot/tl/mark.cc b/spot/tl/mark.cc index 884d8cd6f..fbc2d6495 100644 --- a/spot/tl/mark.cc +++ b/spot/tl/mark.cc @@ -58,25 +58,25 @@ namespace spot case op::UConcat: case op::Concat: case op::Fusion: - res = f; - break; + res = f; + break; case op::NegClosure: - res = formula::NegClosureMarked(f[0]); - break; + res = formula::NegClosureMarked(f[0]); + break; case op::EConcat: - res = formula::EConcatMarked(f[0], f[1]); - break; + res = formula::EConcatMarked(f[0], f[1]); + break; case op::Or: case op::And: - res = f.map([this](formula f) - { - return this->mark_concat_ops(f); - }); - break; + res = f.map([this](formula f) + { + return this->mark_concat_ops(f); + }); + break; case op::Xor: case op::Implies: case op::Equiv: - SPOT_UNIMPLEMENTED(); + SPOT_UNIMPLEMENTED(); } markops_[f] = res; @@ -95,7 +95,7 @@ namespace spot auto recurse = [this](formula f) { - return this->simplify_mark(f); + return this->simplify_mark(f); }; formula res; @@ -119,58 +119,58 @@ namespace spot case op::EConcat: case op::EConcatMarked: case op::UConcat: - res = f; - break; + res = f; + break; case op::Or: - res = f.map(recurse); - break; + res = f.map(recurse); + break; case op::And: - { - std::set> empairs; - std::set nmset; - std::vector elist; - std::vector nlist; - std::vector v; + { + std::set> empairs; + std::set nmset; + std::vector elist; + std::vector nlist; + std::vector v; - for (auto c: f) - { - if (c.is(op::EConcatMarked)) - { - empairs.emplace(c[0], c[1]); - v.push_back(c.map(recurse)); - } - else if (c.is(op::EConcat)) - { - elist.push_back(c); - } - else if (c.is(op::NegClosureMarked)) - { - nmset.insert(c[0]); - v.push_back(c.map(recurse)); - } - else if (c.is(op::NegClosure)) - { - nlist.push_back(c); - } - else - { - v.push_back(c); - } - } - // Keep only the non-marked EConcat for which we - // have not seen a similar EConcatMarked. - for (auto e: elist) - if (empairs.find(std::make_pair(e[0], e[1])) - == empairs.end()) - v.push_back(e); - // Keep only the non-marked NegClosure for which we - // have not seen a similar NegClosureMarked. - for (auto n: nlist) - if (nmset.find(n[0]) == nmset.end()) - v.push_back(n); - res = formula::And(v); - } - break; + for (auto c: f) + { + if (c.is(op::EConcatMarked)) + { + empairs.emplace(c[0], c[1]); + v.push_back(c.map(recurse)); + } + else if (c.is(op::EConcat)) + { + elist.push_back(c); + } + else if (c.is(op::NegClosureMarked)) + { + nmset.insert(c[0]); + v.push_back(c.map(recurse)); + } + else if (c.is(op::NegClosure)) + { + nlist.push_back(c); + } + else + { + v.push_back(c); + } + } + // Keep only the non-marked EConcat for which we + // have not seen a similar EConcatMarked. + for (auto e: elist) + if (empairs.find(std::make_pair(e[0], e[1])) + == empairs.end()) + v.push_back(e); + // Keep only the non-marked NegClosure for which we + // have not seen a similar NegClosureMarked. + for (auto n: nlist) + if (nmset.find(n[0]) == nmset.end()) + v.push_back(n); + res = formula::And(v); + } + break; case op::Xor: case op::Implies: case op::Equiv: @@ -181,7 +181,7 @@ namespace spot case op::FStar: case op::Concat: case op::Fusion: - SPOT_UNIMPLEMENTED(); + SPOT_UNIMPLEMENTED(); } simpmark_[f] = res; diff --git a/spot/tl/mutation.cc b/spot/tl/mutation.cc index 131cab8dc..ed4c51ccd 100644 --- a/spot/tl/mutation.cc +++ b/spot/tl/mutation.cc @@ -37,12 +37,12 @@ namespace spot formula substitute_ap(formula f, formula ap_src, formula ap_dst) { return f.map([&](formula f) - { - if (f == ap_src) - return ap_dst; - else - return substitute_ap(f, ap_src, ap_dst); - }); + { + if (f == ap_src) + return ap_dst; + else + return substitute_ap(f, ap_src, ap_dst); + }); } typedef std::vector vec; @@ -58,229 +58,229 @@ namespace spot formula mutate(formula f) { - auto recurse = [this](formula f) - { - return this->mutate(f); - }; + auto recurse = [this](formula f) + { + return this->mutate(f); + }; - switch (f.kind()) - { - case op::ff: - case op::tt: - case op::eword: - return f; - case op::ap: - if (opts_ & Mut_Ap2Const) - { - if (mutation_counter_-- == 0) - return formula::tt(); - if (mutation_counter_-- == 0) - return formula::ff(); - } - return f; - case op::Not: - case op::X: - case op::F: - case op::G: - if ((opts_ & Mut_Remove_Ops) - && mutation_counter_-- == 0) - return f[0]; - // fall through - case op::Closure: - case op::NegClosure: - case op::NegClosureMarked: - if (mutation_counter_ < 0) - return f; - else - return f.map(recurse); - case op::Or: - case op::OrRat: - case op::And: - case op::AndRat: - case op::AndNLM: - case op::Concat: - case op::Fusion: - { - int mos = f.size(); - if (opts_ & Mut_Remove_Multop_Operands) - { - for (int i = 0; i < mos; ++i) - if (mutation_counter_-- == 0) - return f.all_but(i); - } + switch (f.kind()) + { + case op::ff: + case op::tt: + case op::eword: + return f; + case op::ap: + if (opts_ & Mut_Ap2Const) + { + if (mutation_counter_-- == 0) + return formula::tt(); + if (mutation_counter_-- == 0) + return formula::ff(); + } + return f; + case op::Not: + case op::X: + case op::F: + case op::G: + if ((opts_ & Mut_Remove_Ops) + && mutation_counter_-- == 0) + return f[0]; + // fall through + case op::Closure: + case op::NegClosure: + case op::NegClosureMarked: + if (mutation_counter_ < 0) + return f; + else + return f.map(recurse); + case op::Or: + case op::OrRat: + case op::And: + case op::AndRat: + case op::AndNLM: + case op::Concat: + case op::Fusion: + { + int mos = f.size(); + if (opts_ & Mut_Remove_Multop_Operands) + { + for (int i = 0; i < mos; ++i) + if (mutation_counter_-- == 0) + return f.all_but(i); + } - if (opts_ & Mut_Split_Ops && f.is(op::AndNLM)) - { - if (mutation_counter_ >= 0 - && mutation_counter_ < 2 * (mos - 1)) - { - vec v1; - vec v2; - v1.push_back(f[0]); - bool reverse = false; - int i = 1; - while (i < mos) - { - if (mutation_counter_-- == 0) - break; - if (mutation_counter_-- == 0) - { - reverse = true; - break; - } - v1.push_back(f[i++]); - } - for (; i < mos; ++i) - v2.push_back(f[i]); - formula first = AndNLM_(v1); - formula second = AndNLM_(v2); - formula ost = formula::one_star(); - if (!reverse) - return AndRat_(Concat_(first, ost), second); - else - return AndRat_(Concat_(second, ost), first); - } - else - { - mutation_counter_ -= 2 * (mos - 1); - } - } + if (opts_ & Mut_Split_Ops && f.is(op::AndNLM)) + { + if (mutation_counter_ >= 0 + && mutation_counter_ < 2 * (mos - 1)) + { + vec v1; + vec v2; + v1.push_back(f[0]); + bool reverse = false; + int i = 1; + while (i < mos) + { + if (mutation_counter_-- == 0) + break; + if (mutation_counter_-- == 0) + { + reverse = true; + break; + } + v1.push_back(f[i++]); + } + for (; i < mos; ++i) + v2.push_back(f[i]); + formula first = AndNLM_(v1); + formula second = AndNLM_(v2); + formula ost = formula::one_star(); + if (!reverse) + return AndRat_(Concat_(first, ost), second); + else + return AndRat_(Concat_(second, ost), first); + } + else + { + mutation_counter_ -= 2 * (mos - 1); + } + } - if (mutation_counter_ < 0) - return f; - else - return f.map(recurse); - } - case op::Xor: - case op::Implies: - case op::Equiv: - case op::U: - case op::R: - case op::W: - case op::M: - case op::EConcat: - case op::EConcatMarked: - case op::UConcat: - { - formula first = f[0]; - formula second = f[1]; - op o = f.kind(); - bool left_is_sere = o == op::EConcat - || o == op::EConcatMarked - || o == op::UConcat; + if (mutation_counter_ < 0) + return f; + else + return f.map(recurse); + } + case op::Xor: + case op::Implies: + case op::Equiv: + case op::U: + case op::R: + case op::W: + case op::M: + case op::EConcat: + case op::EConcatMarked: + case op::UConcat: + { + formula first = f[0]; + formula second = f[1]; + op o = f.kind(); + bool left_is_sere = o == op::EConcat + || o == op::EConcatMarked + || o == op::UConcat; - if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0) - { - if (!left_is_sere) - return first; - else if (o == op::UConcat) - return formula::NegClosure(first); - else // EConcat or EConcatMarked - return formula::Closure(first); - } - if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0) - return second; - if (opts_ & Mut_Rewrite_Ops) - { - switch (o) - { - case op::U: - if (mutation_counter_-- == 0) - return formula::W(first, second); - break; - case op::M: - if (mutation_counter_-- == 0) - return formula::R(first, second); - if (mutation_counter_-- == 0) - return formula::U(second, first); - break; - case op::R: - if (mutation_counter_-- == 0) - return formula::W(second, first); - break; - default: - break; - } - } - if (opts_ & Mut_Split_Ops) - { - switch (o) - { - case op::Equiv: - if (mutation_counter_-- == 0) - return formula::Implies(first, second); - if (mutation_counter_-- == 0) - return formula::Implies(second, first); - if (mutation_counter_-- == 0) - return formula::And({first, second}); - if (mutation_counter_-- == 0) - { - // Negate the two argument sequentially (in this - // case right before left, otherwise different - // compilers will make different choices. - auto right = formula::Not(second); - return formula::And({formula::Not(first), right}); - } - break; - case op::Xor: - if (mutation_counter_-- == 0) - return formula::And({first, formula::Not(second)}); - if (mutation_counter_-- == 0) - return formula::And({formula::Not(first), second}); - break; - default: - break; - } - } - if (mutation_counter_ < 0) - return f; - else - return f.map(recurse); - } - case op::Star: - case op::FStar: - { - formula c = f[0]; - op o = f.kind(); - if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0) - return c; - if (opts_ & Mut_Simplify_Bounds) - { - auto min = f.min(); - auto max = f.max(); - if (min > 0) - { - if (mutation_counter_-- == 0) - return formula::bunop(o, c, min - 1, max); - if (mutation_counter_-- == 0) - return formula::bunop(o, c, 0, max); - } - if (max != formula::unbounded()) - { - if (max > min && mutation_counter_-- == 0) - return formula::bunop(o, c, min, max - 1); - if (mutation_counter_-- == 0) - return formula::bunop(o, c, min, - formula::unbounded()); - } - } - if (mutation_counter_ < 0) - return f; - else - return f.map(recurse); - } - } - SPOT_UNREACHABLE(); + if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0) + { + if (!left_is_sere) + return first; + else if (o == op::UConcat) + return formula::NegClosure(first); + else // EConcat or EConcatMarked + return formula::Closure(first); + } + if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0) + return second; + if (opts_ & Mut_Rewrite_Ops) + { + switch (o) + { + case op::U: + if (mutation_counter_-- == 0) + return formula::W(first, second); + break; + case op::M: + if (mutation_counter_-- == 0) + return formula::R(first, second); + if (mutation_counter_-- == 0) + return formula::U(second, first); + break; + case op::R: + if (mutation_counter_-- == 0) + return formula::W(second, first); + break; + default: + break; + } + } + if (opts_ & Mut_Split_Ops) + { + switch (o) + { + case op::Equiv: + if (mutation_counter_-- == 0) + return formula::Implies(first, second); + if (mutation_counter_-- == 0) + return formula::Implies(second, first); + if (mutation_counter_-- == 0) + return formula::And({first, second}); + if (mutation_counter_-- == 0) + { + // Negate the two argument sequentially (in this + // case right before left, otherwise different + // compilers will make different choices. + auto right = formula::Not(second); + return formula::And({formula::Not(first), right}); + } + break; + case op::Xor: + if (mutation_counter_-- == 0) + return formula::And({first, formula::Not(second)}); + if (mutation_counter_-- == 0) + return formula::And({formula::Not(first), second}); + break; + default: + break; + } + } + if (mutation_counter_ < 0) + return f; + else + return f.map(recurse); + } + case op::Star: + case op::FStar: + { + formula c = f[0]; + op o = f.kind(); + if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0) + return c; + if (opts_ & Mut_Simplify_Bounds) + { + auto min = f.min(); + auto max = f.max(); + if (min > 0) + { + if (mutation_counter_-- == 0) + return formula::bunop(o, c, min - 1, max); + if (mutation_counter_-- == 0) + return formula::bunop(o, c, 0, max); + } + if (max != formula::unbounded()) + { + if (max > min && mutation_counter_-- == 0) + return formula::bunop(o, c, min, max - 1); + if (mutation_counter_-- == 0) + return formula::bunop(o, c, min, + formula::unbounded()); + } + } + if (mutation_counter_ < 0) + return f; + else + return f.map(recurse); + } + } + SPOT_UNREACHABLE(); } formula get_mutation(int n) { - mutation_counter_ = n; - formula mut = mutate(f_); - if (mut == f_) - return nullptr; - return mut; + mutation_counter_ = n; + formula mut = mutate(f_); + if (mut == f_) + return nullptr; + return mut; } }; @@ -291,13 +291,13 @@ namespace spot assert(left != nullptr); assert(right != nullptr); if (left == right) - return false; + return false; auto ll = length(left); auto lr = length(right); if (ll < lr) - return true; + return true; if (ll > lr) - return false; + return false; return left < right; } @@ -305,55 +305,55 @@ namespace spot void single_mutation_rec(formula f, fset_t& mutations, unsigned opts, - unsigned& n, unsigned m) + unsigned& n, unsigned m) { if (m == 0) - { - if (mutations.insert(f).second) - --n; - } + { + if (mutations.insert(f).second) + --n; + } else - { - formula mut; - int i = 0; - mutator mv(f, opts); - while (n > 0 && ((mut = mv.get_mutation(i++)) != nullptr)) - single_mutation_rec(mut, mutations, opts, n, m - 1); - } + { + formula mut; + int i = 0; + mutator mv(f, opts); + while (n > 0 && ((mut = mv.get_mutation(i++)) != nullptr)) + single_mutation_rec(mut, mutations, opts, n, m - 1); + } } void replace_ap_rec(formula f, fset_t& mutations, unsigned opts, - unsigned& n, unsigned m) + unsigned& n, unsigned m) { if (m == 0) - { - if (mutations.insert(f).second) - --n; - } + { + if (mutations.insert(f).second) + --n; + } else - { - if (!n) - return; - auto aps = - std::unique_ptr(atomic_prop_collect(f)); - for (auto ap1: *aps) - for (auto ap2: *aps) - { - if (ap1 == ap2) - continue; - auto mut = substitute_ap(f, ap1, ap2); - replace_ap_rec(mut, mutations, opts, n, m - 1); - if (!n) - return; - } - } + { + if (!n) + return; + auto aps = + std::unique_ptr(atomic_prop_collect(f)); + for (auto ap1: *aps) + for (auto ap2: *aps) + { + if (ap1 == ap2) + continue; + auto mut = substitute_ap(f, ap1, ap2); + replace_ap_rec(mut, mutations, opts, n, m - 1); + if (!n) + return; + } + } } } std::vector mutate(formula f, unsigned opts, unsigned max_output, - unsigned mutation_count, bool sort) + unsigned mutation_count, bool sort) { fset_t mutations; single_mutation_rec(f, mutations, opts, max_output, mutation_count); diff --git a/spot/tl/mutation.hh b/spot/tl/mutation.hh index aee2ef12b..bef46345f 100644 --- a/spot/tl/mutation.hh +++ b/spot/tl/mutation.hh @@ -38,8 +38,8 @@ namespace spot SPOT_API std::vector mutate(formula f, - unsigned opts = Mut_All, - unsigned max_output = -1U, - unsigned mutation_count = 1, - bool sort = true); + unsigned opts = Mut_All, + unsigned max_output = -1U, + unsigned mutation_count = 1, + bool sort = true); } diff --git a/spot/tl/parse.hh b/spot/tl/parse.hh index 4fdd21ff1..01b91125c 100644 --- a/spot/tl/parse.hh +++ b/spot/tl/parse.hh @@ -94,8 +94,8 @@ namespace spot /// \param shift how many characters to add to the error locations /// \return \c true iff any diagnostic was output. bool format_errors(std::ostream& os, - const std::string& input, - unsigned shift); + const std::string& input, + unsigned shift); }; @@ -119,10 +119,10 @@ namespace spot /// \warning This function is not reentrant. SPOT_API parsed_formula parse_infix_psl(const std::string& ltl_string, - environment& env = - default_environment::instance(), - bool debug = false, - bool lenient = false); + environment& env = + default_environment::instance(), + bool debug = false, + bool lenient = false); /// \brief Build a Boolean formula from a string. /// \param ltl_string The string to parse. @@ -142,10 +142,10 @@ namespace spot /// \warning This function is not reentrant. SPOT_API parsed_formula parse_infix_boolean(const std::string& ltl_string, - environment& env = - default_environment::instance(), - bool debug = false, - bool lenient = false); + environment& env = + default_environment::instance(), + bool debug = false, + bool lenient = false); /// \brief Build a formula from an LTL string in LBT's format. /// \param ltl_string The string to parse. @@ -167,9 +167,9 @@ namespace spot /// \warning This function is not reentrant. SPOT_API parsed_formula parse_prefix_ltl(const std::string& ltl_string, - environment& env = - default_environment::instance(), - bool debug = false); + environment& env = + default_environment::instance(), + bool debug = false); /// \brief A simple wrapper to parse_infix_psl() and parse_prefix_ltl(). /// @@ -179,7 +179,7 @@ namespace spot /// parse_infix_psl() as a parse_error exception. SPOT_API formula parse_formula(const std::string& ltl_string, - environment& env = default_environment::instance()); + environment& env = default_environment::instance()); /// \brief Build a formula from a string representing a SERE. /// \param sere_string The string to parse. @@ -200,10 +200,10 @@ namespace spot /// \warning This function is not reentrant. SPOT_API parsed_formula parse_infix_sere(const std::string& sere_string, - environment& env = - default_environment::instance(), - bool debug = false, - bool lenient = false); + environment& env = + default_environment::instance(), + bool debug = false, + bool lenient = false); /// \brief Fix location of diagnostics assuming the input is utf8. /// @@ -230,7 +230,7 @@ namespace spot SPOT_API void fix_utf8_locations(const std::string& input_string, - parse_error_list& error_list); + parse_error_list& error_list); /// @} } diff --git a/spot/tl/print.cc b/spot/tl/print.cc index 43196c58e..ad55a93b6 100644 --- a/spot/tl/print.cc +++ b/spot/tl/print.cc @@ -14,7 +14,7 @@ // // Spot is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public // License for more details. // // You should have received a copy of the GNU General Public License @@ -114,20 +114,20 @@ namespace spot const char* spin_kw[] = { "false", // 0 doesn't work from the command line "true", // 1 doesn't work from the command line - "[*0]", // not supported - " xor ", // rewritten + "[*0]", // not supported + " xor ", // rewritten " -> ", " <-> ", " U ", " V ", - " W ", // rewritten - " M ", // rewritten - "<>-> ", // not supported - "<>=> ", // not supported - "<>+> ", // not supported - "<>=+> ", // not supported - "[]-> ", // not supported - "[]=> ", // not supported + " W ", // rewritten + " M ", // rewritten + "<>-> ", // not supported + "<>=> ", // not supported + "<>+> ", // not supported + "<>=+> ", // not supported + "[]-> ", // not supported + "[]=> ", // not supported "!", "X", "<>", @@ -135,58 +135,58 @@ namespace spot " || ", " || ", " && ", - " && ", // not supported - " & ", // not supported - ";", // not supported - ":", // not supported - "{", // not supported - "}", // not supported - "]", // not supported - "[*", // not supported - "[+]", // not supported - "[:*", // not supported - "[:+]", // not supported - "[=", // not supported - "[->", // not supported + " && ", // not supported + " & ", // not supported + ";", // not supported + ":", // not supported + "{", // not supported + "}", // not supported + "]", // not supported + "[*", // not supported + "[+]", // not supported + "[:*", // not supported + "[:+]", // not supported + "[=", // not supported + "[->", // not supported }; const char* wring_kw[] = { "FALSE", "TRUE", - "[*0]", // not supported + "[*0]", // not supported " ^ ", " -> ", " <-> ", " U ", " R ", - " W ", // rewritten - " M ", // rewritten - "<>-> ", // not supported - "<>=> ", // not supported - "<>+> ", // not supported - "<>=+> ", // not supported - "[]-> ", // not supported - "[]=> ", // not supported + " W ", // rewritten + " M ", // rewritten + "<>-> ", // not supported + "<>=> ", // not supported + "<>+> ", // not supported + "<>=+> ", // not supported + "[]-> ", // not supported + "[]=> ", // not supported "!", "X", "F", "G", " + ", - " | ", // not supported + " | ", // not supported " * ", - " && ", // not supported - " & ", // not supported - ";", // not supported - ":", // not supported - "{", // not supported - "}", // not supported - "]", // not supported - "[*", // not supported - "[+]", // not supported - "[:*", // not supported - "[:+]", // not supported - "[=", // not supported - "[->", // not supported + " && ", // not supported + " & ", // not supported + ";", // not supported + ":", // not supported + "{", // not supported + "}", // not supported + "]", // not supported + "[*", // not supported + "[+]", // not supported + "[:*", // not supported + "[:+]", // not supported + "[=", // not supported + "[->", // not supported }; const char* utf8_kw[] = { @@ -317,19 +317,19 @@ namespace spot // unary operator, or be the name of an existing constant or // operator. Also they should start with an letter. if (!*str - || *str == 'F' - || *str == 'G' - || *str == 'X' - || !(isalpha(*str) || *str == '_' || *str == '.') - || ((*str == 'U' || *str == 'W' || *str == 'M' || *str == 'R') - && str[1] == 0) - || !strcasecmp(str, "true") - || !strcasecmp(str, "false")) - return false; + || *str == 'F' + || *str == 'G' + || *str == 'X' + || !(isalpha(*str) || *str == '_' || *str == '.') + || ((*str == 'U' || *str == 'W' || *str == 'M' || *str == 'R') + && str[1] == 0) + || !strcasecmp(str, "true") + || !strcasecmp(str, "false")) + return false; // The remaining of the word must be alphanumeric. while (*++str) - if (!(isalnum(*str) || *str == '_' || *str == '.')) - return false; + if (!(isalnum(*str) || *str == '_' || *str == '.')) + return false; return true; } @@ -348,9 +348,9 @@ namespace spot assert(i + 1 < mo.size()); formula b = strip_star_not(mo[i]); if (b == nullptr || !b.is_boolean()) - return nullptr; + return nullptr; if (mo[i + 1] == b) - return b; + return b; return nullptr; } @@ -358,490 +358,490 @@ namespace spot { public: to_string_visitor(std::ostream& os, - bool full_parent = false, - bool ratexp = false, - const char** kw = spot_kw) - : os_(os), top_level_(true), - full_parent_(full_parent), in_ratexp_(ratexp), - kw_(kw) - { - } + bool full_parent = false, + bool ratexp = false, + const char** kw = spot_kw) + : os_(os), top_level_(true), + full_parent_(full_parent), in_ratexp_(ratexp), + kw_(kw) + { + } void - openp() const + openp() const { - if (in_ratexp_) - emit(KOpenSERE); - else - os_ << '('; + if (in_ratexp_) + emit(KOpenSERE); + else + os_ << '('; } void - closep() const + closep() const { - if (in_ratexp_) - emit(KCloseSERE); - else - os_ << ')'; + if (in_ratexp_) + emit(KCloseSERE); + else + os_ << ')'; } std::ostream& - emit(int symbol) const + emit(int symbol) const { - return os_ << kw_[symbol]; + return os_ << kw_[symbol]; } void - visit(formula f) + visit(formula f) { - bool top_level = top_level_; - top_level_ = false; + bool top_level = top_level_; + top_level_ = false; - auto s = f.size(); - bool want_par = (full_parent_ || s > 1) && !top_level; - if (want_par) - openp(); + auto s = f.size(); + bool want_par = (full_parent_ || s > 1) && !top_level; + if (want_par) + openp(); - auto emit_bunop_child = [this](formula b) - { - // b[*] is OK, no need to print {b}[*]. However we want - // braces for {!b}[*], the only unary operator that can - // be nested with Star/FStar. - // If full_parent_ is set, we do NOT emit those extra - // braces, because they are already output for the node - // below. - bool need_parent = (!full_parent_ && b.is(op::Not)); - if (need_parent) - openp(); - this->visit(b); - if (need_parent) - closep(); - }; + auto emit_bunop_child = [this](formula b) + { + // b[*] is OK, no need to print {b}[*]. However we want + // braces for {!b}[*], the only unary operator that can + // be nested with Star/FStar. + // If full_parent_ is set, we do NOT emit those extra + // braces, because they are already output for the node + // below. + bool need_parent = (!full_parent_ && b.is(op::Not)); + if (need_parent) + openp(); + this->visit(b); + if (need_parent) + closep(); + }; - op o = f.kind(); - switch (o) - { - case op::ff: - emit(KFalse); - break; - case op::tt: - emit(KTrue); - break; - case op::eword: - emit(KEmptyWord); - break; - case op::ap: - { - const std::string& str = f.ap_name(); - if (!is_bare_word(str.c_str())) - { - // Spin 6 supports atomic propositions such as (a == 0) - // as long as they are enclosed in parentheses. - if (kw_ == sclatex_kw || kw_ == latex_kw) - escape_latex(os_ << "``\\mathit{", str) - << "}\\textrm{''}"; - else if (kw_ != spin_kw) - escape_str(os_ << '"', str) << '"'; - else if (!full_parent_) - os_ << '(' << str << ')'; - else - os_ << str; - } - else - { - if (kw_ == latex_kw || kw_ == sclatex_kw) - { - size_t s = str.size(); - while (str[s - 1] >= '0' && str[s - 1] <= '9') - { - --s; - // bare words cannot start with digits - assert(s != 0); - } - if (s > 1) - os_ << "\\mathit{"; - escape_latex(os_, str.substr(0, s)); - if (s > 1) - os_ << '}'; - if (s != str.size()) - os_ << "_{" - << str.substr(s) - << '}'; - } - else - { - os_ << str; - } - } - if (kw_ == wring_kw) - os_ << "=1"; + op o = f.kind(); + switch (o) + { + case op::ff: + emit(KFalse); + break; + case op::tt: + emit(KTrue); + break; + case op::eword: + emit(KEmptyWord); + break; + case op::ap: + { + const std::string& str = f.ap_name(); + if (!is_bare_word(str.c_str())) + { + // Spin 6 supports atomic propositions such as (a == 0) + // as long as they are enclosed in parentheses. + if (kw_ == sclatex_kw || kw_ == latex_kw) + escape_latex(os_ << "``\\mathit{", str) + << "}\\textrm{''}"; + else if (kw_ != spin_kw) + escape_str(os_ << '"', str) << '"'; + else if (!full_parent_) + os_ << '(' << str << ')'; + else + os_ << str; + } + else + { + if (kw_ == latex_kw || kw_ == sclatex_kw) + { + size_t s = str.size(); + while (str[s - 1] >= '0' && str[s - 1] <= '9') + { + --s; + // bare words cannot start with digits + assert(s != 0); + } + if (s > 1) + os_ << "\\mathit{"; + escape_latex(os_, str.substr(0, s)); + if (s > 1) + os_ << '}'; + if (s != str.size()) + os_ << "_{" + << str.substr(s) + << '}'; + } + else + { + os_ << str; + } + } + if (kw_ == wring_kw) + os_ << "=1"; - } - break; - case op::Not: - { - formula c = f[0]; - if (c.is(op::ap)) - { - // If we negate a single letter in UTF-8, use a - // combining overline. - if (!full_parent_ && kw_ == utf8_kw) - { - auto& name = c.ap_name(); - if (name.size() == 1 && is_bare_word(name.c_str())) - { - os_ << name << "̅"; - break; - } - } - // If we negate an atomic proposition for Wring, - // output prop=0. - if (kw_ == wring_kw) - { - auto& name = c.ap_name(); - if (is_bare_word(name.c_str())) - { - os_ << name << "=0"; - break; - } - } - } - emit(KNot); - visit(c); - break; - } - case op::X: - emit(KX); - visit(f[0]); - break; - case op::F: - emit(KF); - visit(f[0]); - break; - case op::G: - emit(KG); - visit(f[0]); - break; - case op::NegClosure: - case op::NegClosureMarked: - emit(KNot); - if (o == op::NegClosureMarked) - os_ << (kw_ == utf8_kw ? "̃": "+"); - // Fall through - case op::Closure: - os_ << '{'; - in_ratexp_ = true; - top_level_ = true; - visit(f[0]); - os_ << '}'; - in_ratexp_ = false; - top_level_ = false; - break; - case op::Xor: - visit(f[0]); - emit(KXor); - visit(f[1]); - break; - case op::Implies: - visit(f[0]); - emit(KImplies); - visit(f[1]); - break; - case op::Equiv: - visit(f[0]); - emit(KEquiv); - visit(f[1]); - break; - case op::U: - visit(f[0]); - emit(KU); - visit(f[1]); - break; - case op::R: - visit(f[0]); - emit(KR); - visit(f[1]); - break; - case op::W: - visit(f[0]); - emit(KW); - visit(f[1]); - break; - case op::M: - visit(f[0]); - emit(KM); - visit(f[1]); - break; - case op::EConcat: - case op::EConcatMarked: - case op::UConcat: - { - in_ratexp_ = true; - openp(); - top_level_ = true; - formula left = f[0]; - formula right = f[1]; - unsigned last = left.size() - 1; - bool onelast = false; - if (left.is(op::Concat) && left[last].is_tt()) - { - visit(left.all_but(last)); - onelast = true; - } - else - { - visit(left); - } - top_level_ = false; - closep(); - in_ratexp_ = false; - if (o == op::UConcat) - { - emit(onelast ? KTriggersNext : KTriggers); - visit(right); - } - else if (o == op::EConcatMarked) - { - emit(onelast ? KSeqMarkedNext : KSeqMarked); - visit(right); - } - else if (o == op::EConcat) - { - if (f[1].is_tt()) - { - os_ << '!'; - // No recursion on right. - } - else - { - emit(onelast ? KSeqNext : KSeq); - visit(right); - } - } - else - { - SPOT_UNREACHABLE(); - } - } - break; - case op::Or: - case op::OrRat: - case op::And: - case op::AndRat: - case op::AndNLM: - case op::Fusion: - { - visit(f[0]); - keyword k = KFalse; // Initialize to something to please GCC. - switch (o) - { - case op::Or: - k = KOr; - break; - case op::OrRat: - k = KOrRat; - break; - case op::And: - k = in_ratexp_ ? KAndRat : KAnd; - break; - case op::AndRat: - k = KAndRat; - break; - case op::AndNLM: - k = KAndNLM; - break; - case op::Fusion: - k = KFusion; - break; - default: - SPOT_UNREACHABLE(); - } - assert(k != KFalse); + } + break; + case op::Not: + { + formula c = f[0]; + if (c.is(op::ap)) + { + // If we negate a single letter in UTF-8, use a + // combining overline. + if (!full_parent_ && kw_ == utf8_kw) + { + auto& name = c.ap_name(); + if (name.size() == 1 && is_bare_word(name.c_str())) + { + os_ << name << "̅"; + break; + } + } + // If we negate an atomic proposition for Wring, + // output prop=0. + if (kw_ == wring_kw) + { + auto& name = c.ap_name(); + if (is_bare_word(name.c_str())) + { + os_ << name << "=0"; + break; + } + } + } + emit(KNot); + visit(c); + break; + } + case op::X: + emit(KX); + visit(f[0]); + break; + case op::F: + emit(KF); + visit(f[0]); + break; + case op::G: + emit(KG); + visit(f[0]); + break; + case op::NegClosure: + case op::NegClosureMarked: + emit(KNot); + if (o == op::NegClosureMarked) + os_ << (kw_ == utf8_kw ? "̃": "+"); + // Fall through + case op::Closure: + os_ << '{'; + in_ratexp_ = true; + top_level_ = true; + visit(f[0]); + os_ << '}'; + in_ratexp_ = false; + top_level_ = false; + break; + case op::Xor: + visit(f[0]); + emit(KXor); + visit(f[1]); + break; + case op::Implies: + visit(f[0]); + emit(KImplies); + visit(f[1]); + break; + case op::Equiv: + visit(f[0]); + emit(KEquiv); + visit(f[1]); + break; + case op::U: + visit(f[0]); + emit(KU); + visit(f[1]); + break; + case op::R: + visit(f[0]); + emit(KR); + visit(f[1]); + break; + case op::W: + visit(f[0]); + emit(KW); + visit(f[1]); + break; + case op::M: + visit(f[0]); + emit(KM); + visit(f[1]); + break; + case op::EConcat: + case op::EConcatMarked: + case op::UConcat: + { + in_ratexp_ = true; + openp(); + top_level_ = true; + formula left = f[0]; + formula right = f[1]; + unsigned last = left.size() - 1; + bool onelast = false; + if (left.is(op::Concat) && left[last].is_tt()) + { + visit(left.all_but(last)); + onelast = true; + } + else + { + visit(left); + } + top_level_ = false; + closep(); + in_ratexp_ = false; + if (o == op::UConcat) + { + emit(onelast ? KTriggersNext : KTriggers); + visit(right); + } + else if (o == op::EConcatMarked) + { + emit(onelast ? KSeqMarkedNext : KSeqMarked); + visit(right); + } + else if (o == op::EConcat) + { + if (f[1].is_tt()) + { + os_ << '!'; + // No recursion on right. + } + else + { + emit(onelast ? KSeqNext : KSeq); + visit(right); + } + } + else + { + SPOT_UNREACHABLE(); + } + } + break; + case op::Or: + case op::OrRat: + case op::And: + case op::AndRat: + case op::AndNLM: + case op::Fusion: + { + visit(f[0]); + keyword k = KFalse; // Initialize to something to please GCC. + switch (o) + { + case op::Or: + k = KOr; + break; + case op::OrRat: + k = KOrRat; + break; + case op::And: + k = in_ratexp_ ? KAndRat : KAnd; + break; + case op::AndRat: + k = KAndRat; + break; + case op::AndNLM: + k = KAndNLM; + break; + case op::Fusion: + k = KFusion; + break; + default: + SPOT_UNREACHABLE(); + } + assert(k != KFalse); - unsigned max = f.size(); - for (unsigned n = 1; n < max; ++n) - { - emit(k); - visit(f[n]); - } - break; - } - case op::Concat: - { - unsigned max = f.size(); + unsigned max = f.size(); + for (unsigned n = 1; n < max; ++n) + { + emit(k); + visit(f[n]); + } + break; + } + case op::Concat: + { + unsigned max = f.size(); - for (unsigned i = 0; i < max; ++i) - { - if (i > 0) - emit(KConcat); - if (i + 1 < max) - { - // Try to match (!b)[*];b - formula b = match_goto(f, i); - if (b != nullptr) - { - emit_bunop_child(b); + for (unsigned i = 0; i < max; ++i) + { + if (i > 0) + emit(KConcat); + if (i + 1 < max) + { + // Try to match (!b)[*];b + formula b = match_goto(f, i); + if (b != nullptr) + { + emit_bunop_child(b); - // Wait... maybe we are looking at (!b)[*];b;(!b)[*] - // in which case it's b[=1]. - if (i + 2 < max && f[i] == f[i + 2]) - { - emit(KEqualBunop); - os_ << '1'; - emit(KCloseBunop); - i += 2; - } - else - { - emit(KGotoBunop); - emit(KCloseBunop); - ++i; - } - continue; - } - // Try to match ((!b)[*];b)[*i..j];(!b)[*] - formula fi = f[i]; - if (fi.is(op::Star)) - { - if (formula b2 = strip_star_not(f[i + 1])) - { - formula fic = fi[0]; - if (fic.is(op::Concat)) - if (formula b1 = match_goto(fic, 0)) - if (b1 == b2) - { - emit_bunop_child(b1); - emit(KEqualBunop); - unsigned min = fi.min(); - os_ << min; - unsigned max = fi.max(); - if (max != min) - { - os_ << ".."; - if (max != formula::unbounded()) - os_ << max; - } - emit(KCloseBunop); - ++i; - continue; - } - } - } - } - visit(f[i]); - } - break; - } - case op::Star: - case op::FStar: - { - formula c = f[0]; - enum { Star, FStar, Goto } sugar = Star; - unsigned default_min = 0; - unsigned default_max = formula::unbounded(); + // Wait... maybe we are looking at (!b)[*];b;(!b)[*] + // in which case it's b[=1]. + if (i + 2 < max && f[i] == f[i + 2]) + { + emit(KEqualBunop); + os_ << '1'; + emit(KCloseBunop); + i += 2; + } + else + { + emit(KGotoBunop); + emit(KCloseBunop); + ++i; + } + continue; + } + // Try to match ((!b)[*];b)[*i..j];(!b)[*] + formula fi = f[i]; + if (fi.is(op::Star)) + { + if (formula b2 = strip_star_not(f[i + 1])) + { + formula fic = fi[0]; + if (fic.is(op::Concat)) + if (formula b1 = match_goto(fic, 0)) + if (b1 == b2) + { + emit_bunop_child(b1); + emit(KEqualBunop); + unsigned min = fi.min(); + os_ << min; + unsigned max = fi.max(); + if (max != min) + { + os_ << ".."; + if (max != formula::unbounded()) + os_ << max; + } + emit(KCloseBunop); + ++i; + continue; + } + } + } + } + visit(f[i]); + } + break; + } + case op::Star: + case op::FStar: + { + formula c = f[0]; + enum { Star, FStar, Goto } sugar = Star; + unsigned default_min = 0; + unsigned default_max = formula::unbounded(); - // Abbreviate "1[*]" as "[*]". - if (!c.is_tt() || o != op::Star) - { - if (o == op::Star) - { - // Is this a Goto? - if (c.is(op::Concat)) - { - unsigned s = c.size(); - if (s == 2) - if (formula b = match_goto(c, 0)) - { - c = b; - sugar = Goto; - } - } - } - else if (o == op::FStar) - { - sugar = FStar; - } - else - { - SPOT_UNREACHABLE(); - } - emit_bunop_child(c); - } + // Abbreviate "1[*]" as "[*]". + if (!c.is_tt() || o != op::Star) + { + if (o == op::Star) + { + // Is this a Goto? + if (c.is(op::Concat)) + { + unsigned s = c.size(); + if (s == 2) + if (formula b = match_goto(c, 0)) + { + c = b; + sugar = Goto; + } + } + } + else if (o == op::FStar) + { + sugar = FStar; + } + else + { + SPOT_UNREACHABLE(); + } + emit_bunop_child(c); + } - unsigned min = f.min(); - unsigned max = f.max(); - bool range = true; - switch (sugar) - { - case Star: - if (min == 1 && max == formula::unbounded()) - { - range = false; - emit(KPlusBunop); - } - else - { - emit(KStarBunop); - } - break; - case FStar: - if (min == 1 && max == formula::unbounded()) - { - range = false; - emit(KFPlusBunop); - } - else - { - emit(KFStarBunop); - } - break; - case Goto: - emit(KGotoBunop); - default_min = 1; - default_max = 1; - break; - } + unsigned min = f.min(); + unsigned max = f.max(); + bool range = true; + switch (sugar) + { + case Star: + if (min == 1 && max == formula::unbounded()) + { + range = false; + emit(KPlusBunop); + } + else + { + emit(KStarBunop); + } + break; + case FStar: + if (min == 1 && max == formula::unbounded()) + { + range = false; + emit(KFPlusBunop); + } + else + { + emit(KFStarBunop); + } + break; + case Goto: + emit(KGotoBunop); + default_min = 1; + default_max = 1; + break; + } - // Beware that the default parameters of the Goto operator are - // not the same as Star or Equal: - // - // [->] = [->1..1] - // [->..] = [->1..unbounded] - // [*] = [*0..unbounded] - // [*..] = [*0..unbounded] - // [=] = [=0..unbounded] - // [=..] = [=0..unbounded] - // - // Strictly speaking [=] is not specified by PSL, and anyway we - // automatically rewrite Exp[=0..unbounded] as - // Exp[*0..unbounded], so we should never have to print [=] - // here. - // - // Also - // [*..] = [*0..unbounded] + // Beware that the default parameters of the Goto operator are + // not the same as Star or Equal: + // + // [->] = [->1..1] + // [->..] = [->1..unbounded] + // [*] = [*0..unbounded] + // [*..] = [*0..unbounded] + // [=] = [=0..unbounded] + // [=..] = [=0..unbounded] + // + // Strictly speaking [=] is not specified by PSL, and anyway we + // automatically rewrite Exp[=0..unbounded] as + // Exp[*0..unbounded], so we should never have to print [=] + // here. + // + // Also + // [*..] = [*0..unbounded] - if (range) - { - if (min != default_min || max != default_max) - { - // Always print the min_, even when it is equal to - // default_min, this way we avoid ambiguities (like - // when reading [*..3] near [->..2]) - os_ << min; - if (min != max) - { - os_ << ".."; - if (max != formula::unbounded()) - os_ << max; - } - } - emit(KCloseBunop); - } - } - break; - } - if (want_par) - closep(); + if (range) + { + if (min != default_min || max != default_max) + { + // Always print the min_, even when it is equal to + // default_min, this way we avoid ambiguities (like + // when reading [*..3] near [->..2]) + os_ << min; + if (min != max) + { + os_ << ".."; + if (max != formula::unbounded()) + os_ << max; + } + } + emit(KCloseBunop); + } + } + break; + } + if (want_par) + closep(); } protected: @@ -855,7 +855,7 @@ namespace spot std::ostream& printer_(std::ostream& os, formula f, bool full_parent, - bool ratexp, const char** kw) + bool ratexp, const char** kw) { to_string_visitor v(os, full_parent, ratexp, kw); v.visit(f); @@ -1010,10 +1010,10 @@ namespace spot is_pnum(const char* str) { if (str[0] != 'p' || str[1] == 0) - return false; + return false; while (*++str) - if (*str < '0' || *str > '9') - return false; + if (*str < '0' || *str > '9') + return false; return true; } @@ -1025,97 +1025,97 @@ namespace spot public: lbt_visitor(std::ostream& os) - : os_(os), first_(true) - { - } + : os_(os), first_(true) + { + } void - visit(formula f) + visit(formula f) { - if (first_) - first_ = false; - else - os_ << ' '; + if (first_) + first_ = false; + else + os_ << ' '; - op o = f.kind(); - switch (o) - { - case op::ff: - os_ << 'f'; - break; - case op::tt: - os_ << 't'; - break; - case op::ap: - { - const std::string& str = f.ap_name(); - if (!is_pnum(str.c_str())) - escape_str(os_ << '"', str) << '"'; - else - os_ << str; - break; - } - case op::Not: - os_ << '!'; - break; - case op::X: - os_ << 'X'; - break; - case op::F: - os_ << 'F'; - break; - case op::G: - os_ << 'G'; - break; - case op::Xor: - os_ << '^'; - break; - case op::Implies: - os_ << 'i'; - break; - case op::Equiv: - os_ << 'e'; - break; - case op::U: - os_ << 'U'; - break; - case op::R: - os_ << 'V'; - break; - case op::W: - os_ << 'W'; - break; - case op::M: - os_ << 'M'; - break; - case op::Or: - for (unsigned i = f.size() - 1; i != 0; --i) - os_ << "| "; - first_ = true; - break; - case op::And: - for (unsigned i = f.size() - 1; i != 0; --i) - os_ << "& "; - first_ = true; - break; - case op::eword: - case op::Closure: - case op::NegClosure: - case op::NegClosureMarked: - case op::EConcat: - case op::EConcatMarked: - case op::UConcat: - case op::OrRat: - case op::AndRat: - case op::AndNLM: - case op::Concat: - case op::Fusion: - case op::Star: - case op::FStar: - SPOT_UNIMPLEMENTED(); - } - for (auto c: f) - visit(c); + op o = f.kind(); + switch (o) + { + case op::ff: + os_ << 'f'; + break; + case op::tt: + os_ << 't'; + break; + case op::ap: + { + const std::string& str = f.ap_name(); + if (!is_pnum(str.c_str())) + escape_str(os_ << '"', str) << '"'; + else + os_ << str; + break; + } + case op::Not: + os_ << '!'; + break; + case op::X: + os_ << 'X'; + break; + case op::F: + os_ << 'F'; + break; + case op::G: + os_ << 'G'; + break; + case op::Xor: + os_ << '^'; + break; + case op::Implies: + os_ << 'i'; + break; + case op::Equiv: + os_ << 'e'; + break; + case op::U: + os_ << 'U'; + break; + case op::R: + os_ << 'V'; + break; + case op::W: + os_ << 'W'; + break; + case op::M: + os_ << 'M'; + break; + case op::Or: + for (unsigned i = f.size() - 1; i != 0; --i) + os_ << "| "; + first_ = true; + break; + case op::And: + for (unsigned i = f.size() - 1; i != 0; --i) + os_ << "& "; + first_ = true; + break; + case op::eword: + case op::Closure: + case op::NegClosure: + case op::NegClosureMarked: + case op::EConcat: + case op::EConcatMarked: + case op::UConcat: + case op::OrRat: + case op::AndRat: + case op::AndNLM: + case op::Concat: + case op::Fusion: + case op::Star: + case op::FStar: + SPOT_UNIMPLEMENTED(); + } + for (auto c: f) + visit(c); } }; diff --git a/spot/tl/print.hh b/spot/tl/print.hh index ed8a0b2b4..07d475be7 100644 --- a/spot/tl/print.hh +++ b/spot/tl/print.hh @@ -34,14 +34,14 @@ namespace spot /// \param os The stream where it should be output. /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::ostream& print_psl(std::ostream& os, formula f, bool full_parent = false); /// \brief Convert a PSL formula into a string which is parsable /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::string str_psl(formula f, bool full_parent = false); @@ -49,15 +49,15 @@ namespace spot /// \param os The stream where it should be output. /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::ostream& print_utf8_psl(std::ostream& os, formula f, - bool full_parent = false); + bool full_parent = false); /// \brief Convert a PSL formula into a utf-8 string which is parsable /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::string str_utf8_psl(formula f, bool full_parent = false); @@ -65,14 +65,14 @@ namespace spot /// \param f The formula to translate. /// \param os The stream where it should be output. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::ostream& print_sere(std::ostream& os, formula f, bool full_parent = false); /// \brief Convert a SERE formula into a string which is parsable /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::string str_sere(formula f, bool full_parent = false); @@ -80,15 +80,15 @@ namespace spot /// \param os The stream where it should be output. /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::ostream& print_utf8_sere(std::ostream& os, formula f, - bool full_parent = false); + bool full_parent = false); /// \brief Convert a SERE formula into a string which is parsable /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::string str_utf8_sere(formula f, bool full_parent = false); @@ -96,15 +96,15 @@ namespace spot /// \param os The stream where it should be output. /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::ostream& print_spin_ltl(std::ostream& os, formula f, - bool full_parent = false); + bool full_parent = false); /// \brief Convert an LTL formula into a string parsable by Spin. /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::string str_spin_ltl(formula f, bool full_parent = false); @@ -123,16 +123,16 @@ namespace spot /// \param os The stream where it should be output. /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::ostream& print_latex_psl(std::ostream& os, formula f, - bool full_parent = false); + bool full_parent = false); /// \brief Output a formula as a LaTeX string which is parsable. /// unless the formula contains automaton operators (used in ELTL formulae). /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::string str_latex_psl(formula f, bool full_parent = false); @@ -140,16 +140,16 @@ namespace spot /// \param os The stream where it should be output. /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::ostream& print_latex_sere(std::ostream& os, formula f, - bool full_parent = false); + bool full_parent = false); /// \brief Output a SERE formula as a LaTeX string which is parsable. /// unless the formula contains automaton operators (used in ELTL formulae). /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::string str_latex_sere(formula f, bool full_parent = false); @@ -159,17 +159,17 @@ namespace spot /// \param os The stream where it should be output. /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::ostream& print_sclatex_psl(std::ostream& os, formula f, - bool full_parent = false); + bool full_parent = false); /// \brief Output a PSL formula as a self-contained LaTeX string. /// /// The result cannot be parsed bacl. /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::string str_sclatex_psl(formula f, bool full_parent = false); @@ -179,17 +179,17 @@ namespace spot /// \param os The stream where it should be output. /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::ostream& print_sclatex_sere(std::ostream& os, formula f, - bool full_parent = false); + bool full_parent = false); /// \brief Output a SERE formula as a self-contained LaTeX string. /// /// The result cannot be parsed bacl. /// \param f The formula to translate. /// \param full_parent Whether or not the string should by fully - /// parenthesized. + /// parenthesized. SPOT_API std::string str_sclatex_sere(formula f, bool full_parent = false); diff --git a/spot/tl/randomltl.cc b/spot/tl/randomltl.cc index aec952a87..7ff96dd39 100644 --- a/spot/tl/randomltl.cc +++ b/spot/tl/randomltl.cc @@ -183,24 +183,24 @@ namespace spot total_2_and_more_ = 0.0; for (unsigned i = 0; i < proba_size_; ++i) { - if (proba_[i].min_n == 1) - { - total_1_ += proba_[i].proba; - if (proba_ + i >= proba_2_) - total_2_ += proba_[i].proba; - if (proba_ + i >= proba_2_or_more_) - total_2_and_more_ += proba_[i].proba; - } - else if (proba_[i].min_n == 2) - { - total_2_ += proba_[i].proba; - if (proba_ + i >= proba_2_or_more_) - total_2_and_more_ += proba_[i].proba; - } - else if (proba_[i].min_n > 2) - total_2_and_more_ += proba_[i].proba; - else - SPOT_UNREACHABLE(); // unexpected max_n + if (proba_[i].min_n == 1) + { + total_1_ += proba_[i].proba; + if (proba_ + i >= proba_2_) + total_2_ += proba_[i].proba; + if (proba_ + i >= proba_2_or_more_) + total_2_and_more_ += proba_[i].proba; + } + else if (proba_[i].min_n == 2) + { + total_2_ += proba_[i].proba; + if (proba_ + i >= proba_2_or_more_) + total_2_and_more_ += proba_[i].proba; + } + else if (proba_[i].min_n > 2) + total_2_and_more_ += proba_[i].proba; + else + SPOT_UNREACHABLE(); // unexpected max_n } assert(total_2_and_more_ >= total_2_); } @@ -216,48 +216,48 @@ namespace spot // Approximate impossible cases. if (n == 1 && total_1_ == 0.0) { - if (total_2_ != 0.0) - n = 2; - else - n = 3; + if (total_2_ != 0.0) + n = 2; + else + n = 3; } else if (n == 2 && total_2_ == 0.0) { - if (total_1_ != 0.0) - n = 1; - else - n = 3; + if (total_1_ != 0.0) + n = 1; + else + n = 3; } else if (n > 2 && total_2_and_more_ == 0.0) { - if (total_1_ != 0.0) - n = 1; - else - assert(total_2_ == 0.0); + if (total_1_ != 0.0) + n = 1; + else + assert(total_2_ == 0.0); } if (n == 1) { - r *= total_1_; - p = proba_; + r *= total_1_; + p = proba_; } else if (n == 2) { - r *= total_2_; - p = proba_2_; + r *= total_2_; + p = proba_2_; } else { - r *= total_2_and_more_; - p = proba_2_or_more_; + r *= total_2_and_more_; + p = proba_2_or_more_; } double s = p->proba; while (s < r) { - ++p; - s += p->proba; + ++p; + s += p->proba; } return p->build(this, n); @@ -271,30 +271,30 @@ namespace spot char* key = strtok(options, "=\t, :;"); while (key) { - char* value = strtok(nullptr, "=\t, :;"); - if (!value) - return key; + char* value = strtok(nullptr, "=\t, :;"); + if (!value) + return key; - char* endptr; - double res = strtod(value, &endptr); - if (*endptr) - return value; + char* endptr; + double res = strtod(value, &endptr); + if (*endptr) + return value; - unsigned i; - for (i = 0; i < proba_size_; ++i) - { - if (('a' <= *proba_[i].name && *proba_[i].name <= 'z' - && !strcasecmp(proba_[i].name, key)) - || !strcmp(proba_[i].name, key)) - { - proba_[i].proba = res; - break; - } - } - if (i == proba_size_) - return key; + unsigned i; + for (i = 0; i < proba_size_; ++i) + { + if (('a' <= *proba_[i].name && *proba_[i].name <= 'z' + && !strcasecmp(proba_[i].name, key)) + || !strcmp(proba_[i].name, key)) + { + proba_[i].proba = res; + break; + } + } + if (i == proba_size_) + return key; - key = strtok(nullptr, "=\t, :;"); + key = strtok(nullptr, "=\t, :;"); } update_sums(); return nullptr; @@ -393,7 +393,7 @@ namespace spot { // FIXME: This looks very fragile. memmove(proba_ + 8, proba_ + 7, - ((proba_ + 16) - (proba_ + 7)) * sizeof(*proba_)); + ((proba_ + 16) - (proba_ + 7)) * sizeof(*proba_)); proba_[7].setup("Closure", 2, closure_builder); proba_[17].setup("EConcat", 3, binop_SERELTL_builder); @@ -402,10 +402,10 @@ namespace spot } randltlgenerator::randltlgenerator(atomic_prop_set aprops, - const option_map& opts, - char* opt_pL, - char* opt_pS, - char* opt_pB) + const option_map& opts, + char* opt_pL, + char* opt_pS, + char* opt_pB) { aprops_ = aprops; output_ = opts.get("output", OUTPUTLTL); @@ -423,51 +423,51 @@ namespace spot switch (output_) { case OUTPUTLTL: - rf_ = new random_ltl(&aprops_); - if (opt_pS) - throw std::invalid_argument("Cannot set sere priorities with " - "LTL output"); - if (opt_pB) - throw std::invalid_argument("Cannot set boolean priorities with " - "LTL output"); - tok_pL = rf_->parse_options(opt_pL); - break; + rf_ = new random_ltl(&aprops_); + if (opt_pS) + throw std::invalid_argument("Cannot set sere priorities with " + "LTL output"); + if (opt_pB) + throw std::invalid_argument("Cannot set boolean priorities with " + "LTL output"); + tok_pL = rf_->parse_options(opt_pL); + break; case OUTPUTBOOL: - rf_ = new random_boolean(&aprops_); - tok_pB = rf_->parse_options(opt_pB); - if (opt_pL) - throw std::invalid_argument("Cannot set ltl priorities with " - "Boolean output"); - if (opt_pS) - throw std::invalid_argument("Cannot set sere priorities " - "with Boolean output"); - break; + rf_ = new random_boolean(&aprops_); + tok_pB = rf_->parse_options(opt_pB); + if (opt_pL) + throw std::invalid_argument("Cannot set ltl priorities with " + "Boolean output"); + if (opt_pS) + throw std::invalid_argument("Cannot set sere priorities " + "with Boolean output"); + break; case OUTPUTSERE: - rf_ = rs_ = new random_sere(&aprops_); - tok_pS = rs_->parse_options(opt_pS); - tok_pB = rs_->rb.parse_options(opt_pB); - if (opt_pL) - throw std::invalid_argument("Cannot set ltl priorities " - "with SERE output"); - break; + rf_ = rs_ = new random_sere(&aprops_); + tok_pS = rs_->parse_options(opt_pS); + tok_pB = rs_->rb.parse_options(opt_pB); + if (opt_pL) + throw std::invalid_argument("Cannot set ltl priorities " + "with SERE output"); + break; case OUTPUTPSL: - rf_ = rp_ = new random_psl(&aprops_); - rs_ = &rp_->rs; - tok_pL = rp_->parse_options(opt_pL); - tok_pS = rs_->parse_options(opt_pS); - tok_pB = rs_->rb.parse_options(opt_pB); - break; + rf_ = rp_ = new random_psl(&aprops_); + rs_ = &rp_->rs; + tok_pL = rp_->parse_options(opt_pL); + tok_pS = rs_->parse_options(opt_pS); + tok_pB = rs_->rb.parse_options(opt_pB); + break; } if (tok_pL) throw std::invalid_argument("failed to parse LTL priorities near " - + std::string(tok_pL)); + + std::string(tok_pL)); if (tok_pS) throw std::invalid_argument("failed to parse SERE priorities near " - + std::string(tok_pS)); + + std::string(tok_pS)); if (tok_pB) throw std::invalid_argument("failed to parse Boolean priorities near " - + std::string(tok_pB)); + + std::string(tok_pB)); spot::srand(opt_seed_); tl_simplifier_options simpl_opts(opt_simpl_level_); @@ -475,12 +475,12 @@ namespace spot } randltlgenerator::randltlgenerator(int aprops_n, - const option_map& opts, - char* opt_pL, - char* opt_pS, - char* opt_pB) + const option_map& opts, + char* opt_pL, + char* opt_pS, + char* opt_pB) : randltlgenerator(create_atomic_prop_set(aprops_n), opts, - opt_pL, opt_pS, opt_pB) + opt_pL, opt_pS, opt_pB) { } @@ -496,24 +496,24 @@ namespace spot formula f = nullptr; do { - ignore = false; - int size = opt_tree_size_min_; - if (size != opt_tree_size_max_) - size = spot::rrand(size, opt_tree_size_max_); - f = rf_->generate(size); + ignore = false; + int size = opt_tree_size_min_; + if (size != opt_tree_size_max_) + size = spot::rrand(size, opt_tree_size_max_); + f = rf_->generate(size); - if (opt_wf_) - { - atomic_prop_set s = aprops_; - remove_some_props(s); - f = formula::And({f, GF_n()}); - } + if (opt_wf_) + { + atomic_prop_set s = aprops_; + remove_some_props(s); + f = formula::And({f, GF_n()}); + } - if (opt_simpl_level_) - f = simpl_.simplify(f); + if (opt_simpl_level_) + f = simpl_.simplify(f); - if (opt_unique_ && !unique_set_.insert(f).second) - ignore = true; + if (opt_unique_ && !unique_set_.insert(f).second) + ignore = true; } while (ignore && --trials); if (trials <= 0) return nullptr; @@ -529,9 +529,9 @@ namespace spot while (n--) { - auto i = s.begin(); - std::advance(i, spot::mrand(s.size())); - s.erase(i); + auto i = s.begin(); + std::advance(i, spot::mrand(s.size())); + s.erase(i); } } @@ -542,11 +542,11 @@ namespace spot formula res = nullptr; for (auto v: aprops_) { - formula f = formula::G(formula::F(v)); - if (res) - res = formula::And({f, res}); - else - res = f; + formula f = formula::G(formula::F(v)); + if (res) + res = formula::And({f, res}); + else + res = f; } return res; } diff --git a/spot/tl/randomltl.hh b/spot/tl/randomltl.hh index 7c310cd39..2fe4892f0 100644 --- a/spot/tl/randomltl.hh +++ b/spot/tl/randomltl.hh @@ -44,7 +44,7 @@ namespace spot { public: random_formula(unsigned proba_size, - const atomic_prop_set* ap): + const atomic_prop_set* ap): proba_size_(proba_size), proba_(new op_proba[proba_size_]), ap_(ap) { } @@ -125,23 +125,23 @@ namespace spot /// The default priorities are defined as follows: /// /** \verbatim - ap n - false 1 - true 1 - not 1 - F 1 - G 1 - X 1 - equiv 1 - implies 1 - xor 1 - R 1 - U 1 - W 1 - M 1 - and 1 - or 1 - \endverbatim */ + ap n + false 1 + true 1 + not 1 + F 1 + G 1 + X 1 + equiv 1 + implies 1 + xor 1 + R 1 + U 1 + W 1 + M 1 + and 1 + or 1 + \endverbatim */ /// /// Where \c n is the number of atomic propositions in the /// set passed to the constructor. @@ -176,16 +176,16 @@ namespace spot /// The default priorities are defined as follows: /// /** \verbatim - ap n - false 1 - true 1 - not 1 - equiv 1 - implies 1 - xor 1 - and 1 - or 1 - \endverbatim */ + ap n + false 1 + true 1 + not 1 + equiv 1 + implies 1 + xor 1 + and 1 + or 1 + \endverbatim */ /// /// Where \c n is the number of atomic propositions in the /// set passed to the constructor. @@ -215,18 +215,18 @@ namespace spot /// The default priorities are defined as follows: /// /** \verbatim - eword 1 - boolform 1 - star 1 - star_b 1 - equal_b 1 - goto_b 1 - and 1 - andNLM 1 - or 1 - concat 1 - fusion 1 - \endverbatim */ + eword 1 + boolform 1 + star 1 + star_b 1 + equal_b 1 + goto_b 1 + and 1 + andNLM 1 + or 1 + concat 1 + fusion 1 + \endverbatim */ /// /// Where "boolfrom" designates a Boolean formula generated /// by random_boolean. @@ -260,26 +260,26 @@ namespace spot /// The default priorities are defined as follows: /// /** \verbatim - ap n - false 1 - true 1 - not 1 - F 1 - G 1 - X 1 - Closure 1 - equiv 1 - implies 1 - xor 1 - R 1 - U 1 - W 1 - M 1 - and 1 - or 1 - EConcat 1 - UConcat 1 - \endverbatim */ + ap n + false 1 + true 1 + not 1 + F 1 + G 1 + X 1 + Closure 1 + equiv 1 + implies 1 + xor 1 + R 1 + U 1 + W 1 + M 1 + and 1 + or 1 + EConcat 1 + UConcat 1 + \endverbatim */ /// /// Where \c n is the number of atomic propositions in the /// set passed to the constructor. @@ -306,14 +306,14 @@ namespace spot public: randltlgenerator(int aprops_n, const option_map& opts, - char* opt_pL = nullptr, - char* opt_pS = nullptr, - char* opt_pB = nullptr); + char* opt_pL = nullptr, + char* opt_pS = nullptr, + char* opt_pB = nullptr); randltlgenerator(atomic_prop_set aprops, const option_map& opts, - char* opt_pL = nullptr, - char* opt_pS = nullptr, - char* opt_pB = nullptr); + char* opt_pL = nullptr, + char* opt_pS = nullptr, + char* opt_pB = nullptr); ~randltlgenerator(); diff --git a/spot/tl/relabel.cc b/spot/tl/relabel.cc index 538ba895e..1eec38a19 100644 --- a/spot/tl/relabel.cc +++ b/spot/tl/relabel.cc @@ -43,15 +43,15 @@ namespace spot { unsigned nn; pnn_generator() - : nn(0) - { - } + : nn(0) + { + } virtual formula next() override { - std::ostringstream s; - s << 'p' << nn++; - return formula::ap(s.str()); + std::ostringstream s; + s << 'p' << nn++; + return formula::ap(s.str()); } }; @@ -59,23 +59,23 @@ namespace spot { public: abc_generator() - : nn(0) - { - } + : nn(0) + { + } unsigned nn; virtual formula next() override { - std::string s; - unsigned n = nn++; - do - { - s.push_back('a' + (n % 26)); - n /= 26; - } - while (n); - return formula::ap(s); + std::string s; + unsigned n = nn++; + do + { + s.push_back('a' + (n % 26)); + n /= 26; + } + while (n); + return formula::ap(s); } }; @@ -89,42 +89,42 @@ namespace spot relabeling_map* oldnames; relabeler(ap_generator* gen, relabeling_map* m) - : gen(gen), oldnames(m) + : gen(gen), oldnames(m) { } ~relabeler() { - delete gen; + delete gen; } formula rename(formula old) { - auto r = newname.emplace(old, nullptr); - if (!r.second) - { - return r.first->second; - } - else - { - formula res = gen->next(); - r.first->second = res; - if (oldnames) - (*oldnames)[res] = old; - return res; - } + auto r = newname.emplace(old, nullptr); + if (!r.second) + { + return r.first->second; + } + else + { + formula res = gen->next(); + r.first->second = res; + if (oldnames) + (*oldnames)[res] = old; + return res; + } } formula visit(formula f) { - if (f.is(op::ap)) - return rename(f); - else - return f.map([this](formula f) - { - return this->visit(f); - }); + if (f.is(op::ap)) + return rename(f); + else + return f.map([this](formula f) + { + return this->visit(f); + }); } }; @@ -139,11 +139,11 @@ namespace spot switch (style) { case Pnn: - gen = new pnn_generator; - break; + gen = new pnn_generator; + break; case Abc: - gen = new abc_generator; - break; + gen = new abc_generator; + break; } relabeler r(gen, m); @@ -236,67 +236,67 @@ namespace spot std::stack s; formula_to_fgraph(fgraph& g): - g(g) - { - } + g(g) + { + } ~formula_to_fgraph() - { - } + { + } void - visit(formula f) + visit(formula f) { - { - // Connect to parent - auto in = g.emplace(f, succ_vec()); - if (!s.empty()) - { - formula top = s.top(); - in.first->second.push_back(top); - g[top].push_back(f); - if (!in.second) - return; - } - else - { - assert(in.second); - } - } - s.push(f); + { + // Connect to parent + auto in = g.emplace(f, succ_vec()); + if (!s.empty()) + { + formula top = s.top(); + in.first->second.push_back(top); + g[top].push_back(f); + if (!in.second) + return; + } + else + { + assert(in.second); + } + } + s.push(f); - unsigned sz = f.size(); - unsigned i = 0; - if (sz > 2 && !f.is_boolean()) - { - /// If we have a formula like (a & b & Xc), consider - /// it as ((a & b) & Xc) in the graph to isolate the - /// Boolean operands as a single node. - formula b = f.boolean_operands(&i); - if (b) - visit(b); - } - for (; i < sz; ++i) - visit(f[i]); - if (sz > 1 && f.is_boolean()) - { - // For Boolean nodes, connect all children in a - // loop. This way the node can only be a cut-point - // if it separates all children from the reset of - // the graph (not only one). - formula pred = f[0]; - for (i = 1; i < sz; ++i) - { - formula next = f[i]; - // Note that we only add an edge in one - // direction, because we are building a cycle - // between all children anyway. - g[pred].push_back(next); - pred = next; - } - g[pred].push_back(f[0]); - } - s.pop(); + unsigned sz = f.size(); + unsigned i = 0; + if (sz > 2 && !f.is_boolean()) + { + /// If we have a formula like (a & b & Xc), consider + /// it as ((a & b) & Xc) in the graph to isolate the + /// Boolean operands as a single node. + formula b = f.boolean_operands(&i); + if (b) + visit(b); + } + for (; i < sz; ++i) + visit(f[i]); + if (sz > 1 && f.is_boolean()) + { + // For Boolean nodes, connect all children in a + // loop. This way the node can only be a cut-point + // if it separates all children from the reset of + // the graph (not only one). + formula pred = f[0]; + for (i = 1; i < sz; ++i) + { + formula next = f[i]; + // Note that we only add an edge in one + // direction, because we are building a cycle + // between all children anyway. + g[pred].push_back(next); + pred = next; + } + g[pred].push_back(f[0]); + } + s.pop(); } }; @@ -307,7 +307,7 @@ namespace spot unsigned num; // serial number, in pre-order unsigned low; // lowest number accessible via unstacked descendants data_entry(unsigned num = 0, unsigned low = 0) - : num(num), low(low) + : num(num), low(low) { } }; @@ -315,7 +315,7 @@ namespace spot struct stack_entry { formula grand_parent; - formula parent; // current node + formula parent; // current node succ_vec::const_iterator current_child; succ_vec::const_iterator last_child; }; @@ -347,58 +347,58 @@ namespace spot s.push(e); while (!s.empty()) - { - stack_entry& e = s.top(); - if (e.current_child != e.last_child) - { - // Skip the edge if it is just the reverse of the one - // we took. - formula child = *e.current_child; - if (child == e.grand_parent) - { - ++e.current_child; - continue; - } - auto i = data.emplace(std::piecewise_construct, - std::forward_as_tuple(child), - std::forward_as_tuple(num, num)); - if (i.second) // New destination. - { - ++num; - const succ_vec& children = g.find(child)->second; - stack_entry newe = { e.parent, child, - children.begin(), children.end() }; - s.push(newe); - } - else // Destination exists. - { - data_entry& dparent = data[e.parent]; - data_entry& dchild = i.first->second; - // If this is a back-edge, update - // the low field of the parent. - if (dchild.num <= dparent.num) - if (dparent.low > dchild.num) - dparent.low = dchild.num; - } - ++e.current_child; - } - else - { - formula grand_parent = e.grand_parent; - formula parent = e.parent; - s.pop(); - if (!s.empty()) - { - data_entry& dparent = data[parent]; - data_entry& dgrand_parent = data[grand_parent]; - if (dparent.low >= dgrand_parent.num // cut-point - && grand_parent.is_boolean()) - c.insert(grand_parent); - if (dparent.low < dgrand_parent.low) - dgrand_parent.low = dparent.low; - } - } - } + { + stack_entry& e = s.top(); + if (e.current_child != e.last_child) + { + // Skip the edge if it is just the reverse of the one + // we took. + formula child = *e.current_child; + if (child == e.grand_parent) + { + ++e.current_child; + continue; + } + auto i = data.emplace(std::piecewise_construct, + std::forward_as_tuple(child), + std::forward_as_tuple(num, num)); + if (i.second) // New destination. + { + ++num; + const succ_vec& children = g.find(child)->second; + stack_entry newe = { e.parent, child, + children.begin(), children.end() }; + s.push(newe); + } + else // Destination exists. + { + data_entry& dparent = data[e.parent]; + data_entry& dchild = i.first->second; + // If this is a back-edge, update + // the low field of the parent. + if (dchild.num <= dparent.num) + if (dparent.low > dchild.num) + dparent.low = dchild.num; + } + ++e.current_child; + } + else + { + formula grand_parent = e.grand_parent; + formula parent = e.parent; + s.pop(); + if (!s.empty()) + { + data_entry& dparent = data[parent]; + data_entry& dgrand_parent = data[grand_parent]; + if (dparent.low >= dgrand_parent.num // cut-point + && grand_parent.is_boolean()) + c.insert(grand_parent); + if (dparent.low < dgrand_parent.low) + dgrand_parent.low = dparent.low; + } + } + } } @@ -407,44 +407,44 @@ namespace spot public: fset& c; bse_relabeler(ap_generator* gen, fset& c, - relabeling_map* m) - : relabeler(gen, m), c(c) + relabeling_map* m) + : relabeler(gen, m), c(c) { } using relabeler::visit; formula - visit(formula f) + visit(formula f) { - if (f.is(op::ap) || (c.find(f) != c.end())) - return rename(f); + if (f.is(op::ap) || (c.find(f) != c.end())) + return rename(f); - unsigned sz = f.size(); - if (sz <= 2) - return f.map([this](formula f) - { - return visit(f); - }); + unsigned sz = f.size(); + if (sz <= 2) + return f.map([this](formula f) + { + return visit(f); + }); - unsigned i = 0; - std::vector res; - /// If we have a formula like (a & b & Xc), consider - /// it as ((a & b) & Xc) in the graph to isolate the - /// Boolean operands as a single node. - formula b = f.boolean_operands(&i); - if (b) - { - res.reserve(sz - i + 1); - res.push_back(visit(b)); - } - else - { - res.reserve(sz); - } - for (; i < sz; ++i) - res.push_back(visit(f[i])); - return formula::multop(f.kind(), res); + unsigned i = 0; + std::vector res; + /// If we have a formula like (a & b & Xc), consider + /// it as ((a & b) & Xc) in the graph to isolate the + /// Boolean operands as a single node. + formula b = f.boolean_operands(&i); + if (b) + { + res.reserve(sz - i + 1); + res.push_back(visit(b)); + } + else + { + res.reserve(sz); + } + for (; i < sz; ++i) + res.push_back(visit(f[i])); + return formula::multop(f.kind(), res); } }; } @@ -471,11 +471,11 @@ namespace spot switch (style) { case Pnn: - gen = new pnn_generator; - break; + gen = new pnn_generator; + break; case Abc: - gen = new abc_generator; - break; + gen = new abc_generator; + break; } bse_relabeler rel(gen, c, m); return rel.visit(f); diff --git a/spot/tl/relabel.hh b/spot/tl/relabel.hh index 9fb6e5270..ffbcce7ef 100644 --- a/spot/tl/relabel.hh +++ b/spot/tl/relabel.hh @@ -36,7 +36,7 @@ namespace spot /// between the new names (keys) and the old names (values). SPOT_API formula relabel(formula f, relabeling_style style, - relabeling_map* m = nullptr); + relabeling_map* m = nullptr); /// \ingroup tl_rewriting @@ -47,5 +47,5 @@ namespace spot /// between the new names (keys) and the old names (values). SPOT_API formula relabel_bse(formula f, relabeling_style style, - relabeling_map* m = nullptr); + relabeling_map* m = nullptr); } diff --git a/spot/tl/remove_x.cc b/spot/tl/remove_x.cc index 77816808c..b1ea493ee 100644 --- a/spot/tl/remove_x.cc +++ b/spot/tl/remove_x.cc @@ -29,59 +29,59 @@ namespace spot remove_x_rec(formula f, atomic_prop_set& aps) { if (f.is_syntactic_stutter_invariant()) - return f; + return f; auto rec = [&aps](formula f) - { - return remove_x_rec(f, aps); - }; + { + return remove_x_rec(f, aps); + }; if (!f.is(op::X)) - return f.map(rec); + return f.map(rec); formula c = rec(f[0]); std::vector vo; for (auto i: aps) - { - // First line - std::vector va1; - formula npi = formula::Not(i); - va1.push_back(i); - va1.push_back(formula::U(i, formula::And({npi, c}))); + { + // First line + std::vector va1; + formula npi = formula::Not(i); + va1.push_back(i); + va1.push_back(formula::U(i, formula::And({npi, c}))); - for (auto j: aps) - if (j != i) - { - // make sure the arguments of OR are created in a - // deterministic order - auto tmp = formula::U(formula::Not(j), npi); - va1.push_back(formula::Or({formula::U(j, npi), tmp})); - } - vo.push_back(formula::And(va1)); - // Second line - std::vector va2; - va2.push_back(npi); - va2.push_back(formula::U(npi, formula::And({i, c}))); - for (auto j: aps) - if (j != i) - { - // make sure the arguments of OR are created in a - // deterministic order - auto tmp = formula::U(formula::Not(j), i); - va2.push_back(formula::Or({formula::U(j, i), tmp})); - } - vo.push_back(formula::And(va2)); - } + for (auto j: aps) + if (j != i) + { + // make sure the arguments of OR are created in a + // deterministic order + auto tmp = formula::U(formula::Not(j), npi); + va1.push_back(formula::Or({formula::U(j, npi), tmp})); + } + vo.push_back(formula::And(va1)); + // Second line + std::vector va2; + va2.push_back(npi); + va2.push_back(formula::U(npi, formula::And({i, c}))); + for (auto j: aps) + if (j != i) + { + // make sure the arguments of OR are created in a + // deterministic order + auto tmp = formula::U(formula::Not(j), i); + va2.push_back(formula::Or({formula::U(j, i), tmp})); + } + vo.push_back(formula::And(va2)); + } // Third line std::vector va3; for (auto i: aps) - { - // make sure the arguments of OR are created in a - // deterministic order - auto tmp = formula::G(formula::Not(i)); - va3.push_back(formula::Or({formula::G(i), tmp})); - } + { + // make sure the arguments of OR are created in a + // deterministic order + auto tmp = formula::G(formula::Not(i)); + va3.push_back(formula::Or({formula::G(i), tmp})); + } va3.push_back(c); vo.push_back(formula::And(va3)); return formula::Or(vo); diff --git a/spot/tl/simplify.cc b/spot/tl/simplify.cc index 2de13b385..db7615028 100644 --- a/spot/tl/simplify.cc +++ b/spot/tl/simplify.cc @@ -61,7 +61,7 @@ namespace spot } tl_simplifier_cache(const bdd_dict_ptr& d, - const tl_simplifier_options& opt) + const tl_simplifier_options& opt) : dict(d), options(opt), lcc(d, true, true, false, false) { options.containment_checks |= options.containment_checks_stronger; @@ -72,11 +72,11 @@ namespace spot print_stats(std::ostream& os) const { os << "simplified formulae: " << simplified_.size() << " entries\n" - << "negative normal form: " << nenoform_.size() << " entries\n" - << "syntactic implications: " << syntimpl_.size() << " entries\n" - << "boolean to bdd: " << as_bdd_.size() << " entries\n" - << "star normal form: " << snf_cache_.size() << " entries\n" - << "boolean isop: " << bool_isop_.size() << " entries\n"; + << "negative normal form: " << nenoform_.size() << " entries\n" + << "syntactic implications: " << syntimpl_.size() << " entries\n" + << "boolean to bdd: " << as_bdd_.size() << " entries\n" + << "star normal form: " << snf_cache_.size() << " entries\n" + << "boolean isop: " << bool_isop_.size() << " entries\n"; } void @@ -92,50 +92,50 @@ namespace spot // Lookup the result in case it has already been computed. f2b_map::const_iterator it = as_bdd_.find(f); if (it != as_bdd_.end()) - return it->second; + return it->second; bdd result = bddfalse; switch (f.kind()) - { - case op::tt: - result = bddtrue; - break; - case op::ff: - result = bddfalse; - break; - case op::ap: - result = bdd_ithvar(dict->register_proposition(f, this)); - break; - case op::Not: - result = !as_bdd(f[0]); - break; - case op::Xor: - result = bdd_apply(as_bdd(f[0]), as_bdd(f[1]), bddop_xor); - break; - case op::Implies: - result = bdd_apply(as_bdd(f[0]), as_bdd(f[1]), bddop_imp); - break; - case op::Equiv: - result = bdd_apply(as_bdd(f[0]), as_bdd(f[1]), bddop_biimp); - break; - case op::And: - { - result = bddtrue; - for (auto c: f) - result &= as_bdd(c); - break; - } - case op::Or: - { - result = bddfalse; - for (auto c: f) - result |= as_bdd(c); - break; - } - default: - SPOT_UNIMPLEMENTED(); - } + { + case op::tt: + result = bddtrue; + break; + case op::ff: + result = bddfalse; + break; + case op::ap: + result = bdd_ithvar(dict->register_proposition(f, this)); + break; + case op::Not: + result = !as_bdd(f[0]); + break; + case op::Xor: + result = bdd_apply(as_bdd(f[0]), as_bdd(f[1]), bddop_xor); + break; + case op::Implies: + result = bdd_apply(as_bdd(f[0]), as_bdd(f[1]), bddop_imp); + break; + case op::Equiv: + result = bdd_apply(as_bdd(f[0]), as_bdd(f[1]), bddop_biimp); + break; + case op::And: + { + result = bddtrue; + for (auto c: f) + result &= as_bdd(c); + break; + } + case op::Or: + { + result = bddfalse; + for (auto c: f) + result |= as_bdd(c); + break; + } + default: + SPOT_UNIMPLEMENTED(); + } // Cache the result before returning. as_bdd_[f] = result; @@ -147,7 +147,7 @@ namespace spot { f2f_map::const_iterator i = nenoform_.find(f); if (i == nenoform_.end()) - return nullptr; + return nullptr; return i->second; } @@ -163,13 +163,13 @@ namespace spot implication(formula f1, formula f2) { trace << "[->] does " << str_psl(f1) << " implies " - << str_psl(f2) << " ?" << std::endl; + << str_psl(f2) << " ?" << std::endl; if ((options.synt_impl && syntactic_implication(f1, f2)) - || (options.containment_checks && contained(f1, f2))) - { - trace << "[->] Yes" << std::endl; - return true; - } + || (options.containment_checks && contained(f1, f2))) + { + trace << "[->] Yes" << std::endl; + return true; + } trace << "[->] No" << std::endl; return false; } @@ -185,7 +185,7 @@ namespace spot contained(formula f1, formula f2) { if (!f1.is_psl_formula() || !f2.is_psl_formula()) - return false; + return false; return lcc.contained(f1, f2); } @@ -193,44 +193,44 @@ namespace spot // If right==true, true if f1 => !f2, false otherwise. bool syntactic_implication_neg(formula f1, formula f2, - bool right); + bool right); // Return true if f1 => !f2 bool contained_neg(formula f1, formula f2) { if (!f1.is_psl_formula() || !f2.is_psl_formula()) - return false; + return false; trace << "[CN] Does (" << str_psl(f1) << ") implies !(" - << str_psl(f2) << ") ?" << std::endl; + << str_psl(f2) << ") ?" << std::endl; if (lcc.contained_neg(f1, f2)) - { - trace << "[CN] Yes" << std::endl; - return true; - } + { + trace << "[CN] Yes" << std::endl; + return true; + } else - { - trace << "[CN] No" << std::endl; - return false; - } + { + trace << "[CN] No" << std::endl; + return false; + } } // Return true if f1 => !f2 bool neg_contained(formula f1, formula f2) { if (!f1.is_psl_formula() || !f2.is_psl_formula()) - return false; + return false; trace << "[NC] Does (" << str_psl(f1) << ") implies !(" - << str_psl(f2) << ") ?" << std::endl; + << str_psl(f2) << ") ?" << std::endl; if (lcc.neg_contained(f1, f2)) - { - trace << "[NC] Yes" << std::endl; - return true; - } + { + trace << "[NC] Yes" << std::endl; + return true; + } else - { - trace << "[NC] No" << std::endl; - return false; - } + { + trace << "[NC] No" << std::endl; + return false; + } } // Return true iff the option set (syntactic implication @@ -241,21 +241,21 @@ namespace spot implication_neg(formula f1, formula f2, bool right) { trace << "[IN] Does " << (right ? "(" : "!(") - << str_psl(f1) << ") implies " - << (right ? "!(" : "(") << str_psl(f2) << ") ?" - << std::endl; + << str_psl(f1) << ") implies " + << (right ? "!(" : "(") << str_psl(f2) << ") ?" + << std::endl; if ((options.synt_impl && syntactic_implication_neg(f1, f2, right)) - || (options.containment_checks && right && contained_neg(f1, f2)) - || (options.containment_checks && !right && neg_contained(f1, f2))) - { - trace << "[IN] Yes" << std::endl; - return true; - } + || (options.containment_checks && right && contained_neg(f1, f2)) + || (options.containment_checks && !right && neg_contained(f1, f2))) + { + trace << "[IN] Yes" << std::endl; + return true; + } else - { - trace << "[IN] No" << std::endl; - return false; - } + { + trace << "[IN] No" << std::endl; + return false; + } } formula @@ -263,7 +263,7 @@ namespace spot { f2f_map::const_iterator i = simplified_.find(f); if (i == simplified_.end()) - return nullptr; + return nullptr; return i->second; } @@ -291,7 +291,7 @@ namespace spot { f2f_map::const_iterator it = bool_isop_.find(f); if (it != bool_isop_.end()) - return it->second; + return it->second; assert(f.is_boolean()); formula res = bdd_to_formula(as_bdd(f), dict); @@ -322,213 +322,213 @@ namespace spot nenoform_rec(formula f, bool negated, tl_simplifier_cache* c); formula equiv_or_xor(bool equiv, formula f1, formula f2, - tl_simplifier_cache* c) + tl_simplifier_cache* c) { auto rec = [c](formula f, bool negated) - { - return nenoform_rec(f, negated, c); - }; + { + return nenoform_rec(f, negated, c); + }; if (equiv) - { - // Rewrite a<=>b as (a&b)|(!a&!b) - auto recurse_f1_true = rec(f1, true); - auto recurse_f1_false = rec(f1, false); - auto recurse_f2_true = rec(f2, true); - auto recurse_f2_false = rec(f2, false); - auto left = formula::And({recurse_f1_false, recurse_f2_false}); - auto right = formula::And({recurse_f1_true, recurse_f2_true}); - return formula::Or({left, right}); - } + { + // Rewrite a<=>b as (a&b)|(!a&!b) + auto recurse_f1_true = rec(f1, true); + auto recurse_f1_false = rec(f1, false); + auto recurse_f2_true = rec(f2, true); + auto recurse_f2_false = rec(f2, false); + auto left = formula::And({recurse_f1_false, recurse_f2_false}); + auto right = formula::And({recurse_f1_true, recurse_f2_true}); + return formula::Or({left, right}); + } else - { - // Rewrite a^b as (a&!b)|(!a&b) - auto recurse_f1_true = rec(f1, true); - auto recurse_f1_false = rec(f1, false); - auto recurse_f2_true = rec(f2, true); - auto recurse_f2_false = rec(f2, false); - auto left = formula::And({recurse_f1_false, recurse_f2_true}); - auto right = formula::And({recurse_f1_true, recurse_f2_false}); - return formula::Or({left, right}); - } + { + // Rewrite a^b as (a&!b)|(!a&b) + auto recurse_f1_true = rec(f1, true); + auto recurse_f1_false = rec(f1, false); + auto recurse_f2_true = rec(f2, true); + auto recurse_f2_false = rec(f2, false); + auto left = formula::And({recurse_f1_false, recurse_f2_true}); + auto right = formula::And({recurse_f1_true, recurse_f2_false}); + return formula::Or({left, right}); + } } formula nenoform_rec(formula f, bool negated, tl_simplifier_cache* c) { if (f.is(op::Not)) - { - negated = !negated; - f = f[0]; - } + { + negated = !negated; + f = f[0]; + } formula key = f; if (negated) - key = formula::Not(f); + key = formula::Not(f); formula result = c->lookup_nenoform(key); if (result) - return result; + return result; if (key.is_in_nenoform() - || (c->options.nenoform_stop_on_boolean && key.is_boolean())) - { - result = key; - } + || (c->options.nenoform_stop_on_boolean && key.is_boolean())) + { + result = key; + } else - { - auto rec = [c](formula f, bool neg) - { - return nenoform_rec(f, neg, c); - }; + { + auto rec = [c](formula f, bool neg) + { + return nenoform_rec(f, neg, c); + }; - switch (op o = f.kind()) - { - case op::ff: - case op::tt: - // Negation of constants is taken care of in the - // constructor of unop::Not, so these cases should be - // caught by nenoform_recursively(). - assert(!negated); - result = f; - break; - case op::ap: - result = negated ? formula::Not(f) : f; - break; - case op::X: - // !Xa == X!a - result = formula::X(rec(f[0], negated)); - break; - case op::F: - // !Fa == G!a - result = formula::unop(negated ? op::G : op::F, - rec(f[0], negated)); - break; - case op::G: - // !Ga == F!a - result = formula::unop(negated ? op::F : op::G, - rec(f[0], negated)); - break; - case op::Closure: - result = formula::unop(negated ? - op::NegClosure : op::Closure, - rec(f[0], false)); - break; - case op::NegClosure: - case op::NegClosureMarked: - result = formula::unop(negated ? op::Closure : o, - rec(f[0], false)); - break; + switch (op o = f.kind()) + { + case op::ff: + case op::tt: + // Negation of constants is taken care of in the + // constructor of unop::Not, so these cases should be + // caught by nenoform_recursively(). + assert(!negated); + result = f; + break; + case op::ap: + result = negated ? formula::Not(f) : f; + break; + case op::X: + // !Xa == X!a + result = formula::X(rec(f[0], negated)); + break; + case op::F: + // !Fa == G!a + result = formula::unop(negated ? op::G : op::F, + rec(f[0], negated)); + break; + case op::G: + // !Ga == F!a + result = formula::unop(negated ? op::F : op::G, + rec(f[0], negated)); + break; + case op::Closure: + result = formula::unop(negated ? + op::NegClosure : op::Closure, + rec(f[0], false)); + break; + case op::NegClosure: + case op::NegClosureMarked: + result = formula::unop(negated ? op::Closure : o, + rec(f[0], false)); + break; - case op::Implies: - if (negated) - // !(a => b) == a & !b - { - auto f2 = rec(f[1], true); - result = formula::And({rec(f[0], false), f2}); - } - else // a => b == !a | b - { - auto f2 = rec(f[1], false); - result = formula::Or({rec(f[0], true), f2}); - } - break; - case op::Xor: - { - // !(a ^ b) == a <=> b - result = equiv_or_xor(negated, f[0], f[1], c); - break; - } - case op::Equiv: - { - // !(a <=> b) == a ^ b - result = equiv_or_xor(!negated, f[0], f[1], c); - break; - } - case op::U: - { - // !(a U b) == !a R !b - auto f1 = rec(f[0], negated); - auto f2 = rec(f[1], negated); - result = formula::binop(negated ? op::R : op::U, f1, f2); - break; - } - case op::R: - { - // !(a R b) == !a U !b - auto f1 = rec(f[0], negated); - auto f2 = rec(f[1], negated); - result = formula::binop(negated ? op::U : op::R, f1, f2); - break; - } - case op::W: - { - // !(a W b) == !a M !b - auto f1 = rec(f[0], negated); - auto f2 = rec(f[1], negated); - result = formula::binop(negated ? op::M : op::W, f1, f2); - break; - } - case op::M: - { - // !(a M b) == !a W !b - auto f1 = rec(f[0], negated); - auto f2 = rec(f[1], negated); - result = formula::binop(negated ? op::W : op::M, f1, f2); - break; - } - case op::Or: - case op::And: - { - unsigned mos = f.size(); - vec v; - for (unsigned i = 0; i < mos; ++i) - v.push_back(rec(f[i], negated)); - op on = o; - if (negated) - on = o == op::Or ? op::And : op::Or; - result = formula::multop(on, v); - break; - } - case op::OrRat: - case op::AndRat: - case op::AndNLM: - case op::Concat: - case op::Fusion: - case op::Star: - case op::FStar: - // !(a*) etc. should never occur. - { - assert(!negated); - result = f.map([c](formula f) - { - return nenoform_rec(f, false, c); - }); - break; - } - case op::EConcat: - case op::EConcatMarked: - { - // !(a <>-> b) == a[]-> !b - auto f1 = f[0]; - auto f2 = f[1]; - result = formula::binop(negated ? op::UConcat : o, - rec(f1, false), rec(f2, negated)); - break; - } - case op::UConcat: - { - // !(a []-> b) == a<>-> !b - auto f1 = f[0]; - auto f2 = f[1]; - result = formula::binop(negated ? op::EConcat : op::UConcat, - rec(f1, false), rec(f2, negated)); - break; - } - case op::eword: - case op::Not: - SPOT_UNREACHABLE(); - } - } + case op::Implies: + if (negated) + // !(a => b) == a & !b + { + auto f2 = rec(f[1], true); + result = formula::And({rec(f[0], false), f2}); + } + else // a => b == !a | b + { + auto f2 = rec(f[1], false); + result = formula::Or({rec(f[0], true), f2}); + } + break; + case op::Xor: + { + // !(a ^ b) == a <=> b + result = equiv_or_xor(negated, f[0], f[1], c); + break; + } + case op::Equiv: + { + // !(a <=> b) == a ^ b + result = equiv_or_xor(!negated, f[0], f[1], c); + break; + } + case op::U: + { + // !(a U b) == !a R !b + auto f1 = rec(f[0], negated); + auto f2 = rec(f[1], negated); + result = formula::binop(negated ? op::R : op::U, f1, f2); + break; + } + case op::R: + { + // !(a R b) == !a U !b + auto f1 = rec(f[0], negated); + auto f2 = rec(f[1], negated); + result = formula::binop(negated ? op::U : op::R, f1, f2); + break; + } + case op::W: + { + // !(a W b) == !a M !b + auto f1 = rec(f[0], negated); + auto f2 = rec(f[1], negated); + result = formula::binop(negated ? op::M : op::W, f1, f2); + break; + } + case op::M: + { + // !(a M b) == !a W !b + auto f1 = rec(f[0], negated); + auto f2 = rec(f[1], negated); + result = formula::binop(negated ? op::W : op::M, f1, f2); + break; + } + case op::Or: + case op::And: + { + unsigned mos = f.size(); + vec v; + for (unsigned i = 0; i < mos; ++i) + v.push_back(rec(f[i], negated)); + op on = o; + if (negated) + on = o == op::Or ? op::And : op::Or; + result = formula::multop(on, v); + break; + } + case op::OrRat: + case op::AndRat: + case op::AndNLM: + case op::Concat: + case op::Fusion: + case op::Star: + case op::FStar: + // !(a*) etc. should never occur. + { + assert(!negated); + result = f.map([c](formula f) + { + return nenoform_rec(f, false, c); + }); + break; + } + case op::EConcat: + case op::EConcatMarked: + { + // !(a <>-> b) == a[]-> !b + auto f1 = f[0]; + auto f2 = f[1]; + result = formula::binop(negated ? op::UConcat : o, + rec(f1, false), rec(f2, negated)); + break; + } + case op::UConcat: + { + // !(a []-> b) == a<>-> !b + auto f1 = f[0]; + auto f2 = f[1]; + result = formula::binop(negated ? op::EConcat : op::UConcat, + rec(f1, false), rec(f2, negated)); + break; + } + case op::eword: + case op::Not: + SPOT_UNREACHABLE(); + } + } c->cache_nenoform(key, result); return result; @@ -550,10 +550,10 @@ namespace spot is_XRM(formula f) { if (!f.is(op::R, op::M)) - return nullptr; + return nullptr; auto left = f[0]; if (!left.is(op::X)) - return nullptr; + return nullptr; return left[0]; } @@ -563,10 +563,10 @@ namespace spot is_XWU(formula f) { if (!f.is(op::W, op::U)) - return nullptr; + return nullptr; auto left = f[0]; if (!left.is(op::X)) - return nullptr; + return nullptr; return left[0]; } @@ -576,20 +576,20 @@ namespace spot is_bXbWU(formula f) { if (!f.is(op::And)) - return nullptr; + return nullptr; unsigned s = f.size(); for (unsigned pos = 0; pos < s; ++pos) - { - auto p = f[pos]; - if (!(p.is(op::X))) - continue; - auto c = p[0]; - if (!c.is(op::U, op::W)) - continue; - formula b = f.all_but(pos); - if (b == c[0]) - return c; - } + { + auto p = f[pos]; + if (!(p.is(op::X))) + continue; + auto c = p[0]; + if (!c.is(op::U, op::W)) + continue; + formula b = f.all_but(pos); + if (b == c[0]) + return c; + } return nullptr; } @@ -599,20 +599,20 @@ namespace spot is_bXbRM(formula f) { if (!f.is(op::Or)) - return nullptr; + return nullptr; unsigned s = f.size(); for (unsigned pos = 0; pos < s; ++pos) - { - auto p = f[pos]; - if (!(p.is(op::X))) - continue; - auto c = p[0]; - if (!c.is(op::R, op::M)) - continue; - formula b = f.all_but(pos); - if (b == c[0]) - return c; - } + { + auto p = f[pos]; + if (!(p.is(op::X))) + continue; + auto c = p[0]; + if (!c.is(op::R, op::M)) + continue; + formula b = f.all_but(pos); + if (b == c[0]) + return c; + } return nullptr; } @@ -637,154 +637,154 @@ namespace spot struct mospliter { enum what { Split_GF = (1 << 0), - Strip_GF = (1 << 1) | (1 << 0), - Split_FG = (1 << 2), - Strip_FG = (1 << 3) | (1 << 2), - Split_F = (1 << 4), - Strip_F = (1 << 5) | (1 << 4), - Split_G = (1 << 6), - Strip_G = (1 << 7) | (1 << 6), - Strip_X = (1 << 8), - Split_U_or_W = (1 << 9), - Split_R_or_M = (1 << 10), - Split_EventUniv = (1 << 11), - Split_Event = (1 << 12), - Split_Univ = (1 << 13), - Split_Bool = (1 << 14) + Strip_GF = (1 << 1) | (1 << 0), + Split_FG = (1 << 2), + Strip_FG = (1 << 3) | (1 << 2), + Split_F = (1 << 4), + Strip_F = (1 << 5) | (1 << 4), + Split_G = (1 << 6), + Strip_G = (1 << 7) | (1 << 6), + Strip_X = (1 << 8), + Split_U_or_W = (1 << 9), + Split_R_or_M = (1 << 10), + Split_EventUniv = (1 << 11), + Split_Event = (1 << 12), + Split_Univ = (1 << 13), + Split_Bool = (1 << 14) }; private: mospliter(unsigned split, tl_simplifier_cache* cache) - : split_(split), c_(cache), - res_GF{(split_ & Split_GF) ? new vec : nullptr}, - res_FG{(split_ & Split_FG) ? new vec : nullptr}, - res_F{(split_ & Split_F) ? new vec : nullptr}, - res_G{(split_ & Split_G) ? new vec : nullptr}, - res_X{(split_ & Strip_X) ? new vec : nullptr}, - res_U_or_W{(split_ & Split_U_or_W) ? new vec : nullptr}, - res_R_or_M{(split_ & Split_R_or_M) ? new vec : nullptr}, - res_Event{(split_ & Split_Event) ? new vec : nullptr}, - res_Univ{(split_ & Split_Univ) ? new vec : nullptr}, - res_EventUniv{(split_ & Split_EventUniv) ? new vec : nullptr}, - res_Bool{(split_ & Split_Bool) ? new vec : nullptr}, - res_other{new vec} + : split_(split), c_(cache), + res_GF{(split_ & Split_GF) ? new vec : nullptr}, + res_FG{(split_ & Split_FG) ? new vec : nullptr}, + res_F{(split_ & Split_F) ? new vec : nullptr}, + res_G{(split_ & Split_G) ? new vec : nullptr}, + res_X{(split_ & Strip_X) ? new vec : nullptr}, + res_U_or_W{(split_ & Split_U_or_W) ? new vec : nullptr}, + res_R_or_M{(split_ & Split_R_or_M) ? new vec : nullptr}, + res_Event{(split_ & Split_Event) ? new vec : nullptr}, + res_Univ{(split_ & Split_Univ) ? new vec : nullptr}, + res_EventUniv{(split_ & Split_EventUniv) ? new vec : nullptr}, + res_Bool{(split_ & Split_Bool) ? new vec : nullptr}, + res_other{new vec} { } public: mospliter(unsigned split, vec v, tl_simplifier_cache* cache) - : mospliter(split, cache) + : mospliter(split, cache) { - for (auto f: v) - { - if (f) // skip null pointers left by previous simplifications - process(f); - } + for (auto f: v) + { + if (f) // skip null pointers left by previous simplifications + process(f); + } } mospliter(unsigned split, formula mo, - tl_simplifier_cache* cache) - : mospliter(split, cache) + tl_simplifier_cache* cache) + : mospliter(split, cache) { - unsigned mos = mo.size(); - for (unsigned i = 0; i < mos; ++i) - { - formula f = simplify_recursively(mo[i], cache); - process(f); - } + unsigned mos = mo.size(); + for (unsigned i = 0; i < mos; ++i) + { + formula f = simplify_recursively(mo[i], cache); + process(f); + } } void process(formula f) { - bool e = f.is_eventual(); - bool u = f.is_universal(); - bool eu = res_EventUniv && e & u && c_->options.favor_event_univ; - switch (f.kind()) - { - case op::X: - if (res_X && !eu) - { - res_X->push_back(f[0]); - return; - } - break; - case op::F: - { - formula c = f[0]; - if (res_FG && u && c.is(op::G)) - { - res_FG->push_back(((split_ & Strip_FG) == Strip_FG - ? c[0] : f)); - return; - } - if (res_F && !eu) - { - res_F->push_back(((split_ & Strip_F) == Strip_F - ? c : f)); - return; - } - break; - } - case op::G: - { - formula c = f[0]; - if (res_GF && e && c.is(op::F)) - { - res_GF->push_back(((split_ & Strip_GF) == Strip_GF - ? c[0] : f)); - return; - } - if (res_G && !eu) - { - res_G->push_back(((split_ & Strip_G) == Strip_G - ? c : f)); - return; - } - break; - } - case op::U: - case op::W: - if (res_U_or_W) - { - res_U_or_W->push_back(f); - return; - } - break; - case op::R: - case op::M: - if (res_R_or_M) - { - res_R_or_M->push_back(f); - return; - } - break; - default: - if (res_Bool && f.is_boolean()) - { - res_Bool->push_back(f); - return; - } - break; - } - if (c_->options.event_univ) - { - if (res_EventUniv && e && u) - { - res_EventUniv->push_back(f); - return; - } - if (res_Event && e) - { - res_Event->push_back(f); - return; - } - if (res_Univ && u) - { - res_Univ->push_back(f); - return; - } - } - res_other->push_back(f); + bool e = f.is_eventual(); + bool u = f.is_universal(); + bool eu = res_EventUniv && e & u && c_->options.favor_event_univ; + switch (f.kind()) + { + case op::X: + if (res_X && !eu) + { + res_X->push_back(f[0]); + return; + } + break; + case op::F: + { + formula c = f[0]; + if (res_FG && u && c.is(op::G)) + { + res_FG->push_back(((split_ & Strip_FG) == Strip_FG + ? c[0] : f)); + return; + } + if (res_F && !eu) + { + res_F->push_back(((split_ & Strip_F) == Strip_F + ? c : f)); + return; + } + break; + } + case op::G: + { + formula c = f[0]; + if (res_GF && e && c.is(op::F)) + { + res_GF->push_back(((split_ & Strip_GF) == Strip_GF + ? c[0] : f)); + return; + } + if (res_G && !eu) + { + res_G->push_back(((split_ & Strip_G) == Strip_G + ? c : f)); + return; + } + break; + } + case op::U: + case op::W: + if (res_U_or_W) + { + res_U_or_W->push_back(f); + return; + } + break; + case op::R: + case op::M: + if (res_R_or_M) + { + res_R_or_M->push_back(f); + return; + } + break; + default: + if (res_Bool && f.is_boolean()) + { + res_Bool->push_back(f); + return; + } + break; + } + if (c_->options.event_univ) + { + if (res_EventUniv && e && u) + { + res_EventUniv->push_back(f); + return; + } + if (res_Event && e) + { + res_Event->push_back(f); + return; + } + if (res_Univ && u) + { + res_Univ->push_back(f); + return; + } + } + res_other->push_back(f); } unsigned split_; @@ -808,2168 +808,2168 @@ namespace spot public: simplify_visitor(tl_simplifier_cache* cache) - : c_(cache), opt_(cache->options) - { - } + : c_(cache), opt_(cache->options) + { + } // if !neg build c&X(c&X(...&X(tail))) with n occurences of c // if neg build !c|X(!c|X(...|X(tail))). formula - dup_b_x_tail(bool neg, formula c, formula tail, unsigned n) + dup_b_x_tail(bool neg, formula c, formula tail, unsigned n) { - op mop; - if (neg) - { - c = formula::Not(c); - mop = op::Or; - } - else - { - mop = op::And; - } - while (n--) - tail = // b&X(tail) or !b|X(tail) - formula::multop(mop, {c, formula::X(tail)}); - return tail; + op mop; + if (neg) + { + c = formula::Not(c); + mop = op::Or; + } + else + { + mop = op::And; + } + while (n--) + tail = // b&X(tail) or !b|X(tail) + formula::multop(mop, {c, formula::X(tail)}); + return tail; } formula - visit(formula f) + visit(formula f) { - formula result = f; + formula result = f; - auto recurse = [this](formula f) - { - return simplify_recursively(f, c_); - }; + auto recurse = [this](formula f) + { + return simplify_recursively(f, c_); + }; - f = f.map(recurse); + f = f.map(recurse); - switch (op o = f.kind()) - { - case op::ff: - case op::tt: - case op::eword: - case op::ap: - case op::Not: - case op::FStar: - return f; - case op::X: - { - formula c = f[0]; - // Xf = f if f is both eventual and universal. - if (c.is_universal() && c.is_eventual()) - { - if (opt_.event_univ) - return c; - // If EventUniv simplification is disabled, use - // only the following basic rewriting rules: - // XGF(f) = GF(f) and XFG(f) = FG(f) - // The former comes from Somenzi&Bloem (CAV'00). - // It's not clear why they do not list the second. - if (opt_.reduce_basics && - (c.is({op::G, op::F}) || c.is({op::F, op::G}))) - return c; - } + switch (op o = f.kind()) + { + case op::ff: + case op::tt: + case op::eword: + case op::ap: + case op::Not: + case op::FStar: + return f; + case op::X: + { + formula c = f[0]; + // Xf = f if f is both eventual and universal. + if (c.is_universal() && c.is_eventual()) + { + if (opt_.event_univ) + return c; + // If EventUniv simplification is disabled, use + // only the following basic rewriting rules: + // XGF(f) = GF(f) and XFG(f) = FG(f) + // The former comes from Somenzi&Bloem (CAV'00). + // It's not clear why they do not list the second. + if (opt_.reduce_basics && + (c.is({op::G, op::F}) || c.is({op::F, op::G}))) + return c; + } - // If Xa = a, keep only a. - if (opt_.containment_checks_stronger - && c_->lcc.equal(f, c)) - return c; + // If Xa = a, keep only a. + if (opt_.containment_checks_stronger + && c_->lcc.equal(f, c)) + return c; - // X(f1 & GF(f2)) = X(f1) & GF(f2) - // X(f1 | GF(f2)) = X(f1) | GF(f2) - // X(f1 & FG(f2)) = X(f1) & FG(f2) - // X(f1 | FG(f2)) = X(f1) | FG(f2) - // - // The above usually make more sense when reversed (see - // them in the And and Or rewritings), except when we - // try to maximaze the size of subformula that do not - // have EventUniv formulae. - if (opt_.favor_event_univ) - if (c.is(op::Or, op::And)) - { - mospliter s(mospliter::Split_EventUniv, c, c_); - op oc = c.kind(); - s.res_EventUniv-> - push_back(unop_multop(op::X, oc, - std::move(*s.res_other))); - formula result = - formula::multop(oc, - std::move(*s.res_EventUniv)); - if (result != f) - result = recurse(result); - return result; - } - return f; - } - case op::F: - { - formula c = f[0]; - // If f is a pure eventuality formula then F(f)=f. - if (opt_.event_univ && c.is_eventual()) - return c; + // X(f1 & GF(f2)) = X(f1) & GF(f2) + // X(f1 | GF(f2)) = X(f1) | GF(f2) + // X(f1 & FG(f2)) = X(f1) & FG(f2) + // X(f1 | FG(f2)) = X(f1) | FG(f2) + // + // The above usually make more sense when reversed (see + // them in the And and Or rewritings), except when we + // try to maximaze the size of subformula that do not + // have EventUniv formulae. + if (opt_.favor_event_univ) + if (c.is(op::Or, op::And)) + { + mospliter s(mospliter::Split_EventUniv, c, c_); + op oc = c.kind(); + s.res_EventUniv-> + push_back(unop_multop(op::X, oc, + std::move(*s.res_other))); + formula result = + formula::multop(oc, + std::move(*s.res_EventUniv)); + if (result != f) + result = recurse(result); + return result; + } + return f; + } + case op::F: + { + formula c = f[0]; + // If f is a pure eventuality formula then F(f)=f. + if (opt_.event_univ && c.is_eventual()) + return c; - if (opt_.reduce_basics) - { - // F(a U b) = F(b) - if (c.is(op::U)) - return recurse(formula::F(c[1])); + if (opt_.reduce_basics) + { + // F(a U b) = F(b) + if (c.is(op::U)) + return recurse(formula::F(c[1])); - // F(a M b) = F(a & b) - if (c.is(op::M)) - return recurse(unop_multop(op::F, op::And, - {c[0], c[1]})); + // F(a M b) = F(a & b) + if (c.is(op::M)) + return recurse(unop_multop(op::F, op::And, + {c[0], c[1]})); - // FX(a) = XF(a) - // FXX(a) = XXF(a) ... - // FXG(a) = XFG(a) = FG(a) ... - if (c.is(op::X)) - return recurse(unop_unop(op::X, op::F, c[0])); + // FX(a) = XF(a) + // FXX(a) = XXF(a) ... + // FXG(a) = XFG(a) = FG(a) ... + if (c.is(op::X)) + return recurse(unop_unop(op::X, op::F, c[0])); - // FG(a & Xb) = FG(a & b) - // FG(a & Gb) = FG(a & b) - if (c.is({op::G, op::And})) - { - formula m = c[0]; - if (!m.is_boolean()) - { - formula out = m.map([](formula f) - { - if (f.is(op::X, op::G)) - return f[0]; - return f; - }); - if (out != m) - return recurse(unop_unop(op::F, op::G, out)); - } - } - } - // if Fa => a, keep a. - if (opt_.containment_checks_stronger - && c_->lcc.contained(f, c)) - return c; + // FG(a & Xb) = FG(a & b) + // FG(a & Gb) = FG(a & b) + if (c.is({op::G, op::And})) + { + formula m = c[0]; + if (!m.is_boolean()) + { + formula out = m.map([](formula f) + { + if (f.is(op::X, op::G)) + return f[0]; + return f; + }); + if (out != m) + return recurse(unop_unop(op::F, op::G, out)); + } + } + } + // if Fa => a, keep a. + if (opt_.containment_checks_stronger + && c_->lcc.contained(f, c)) + return c; - // Disabled by default: - // F(f1 & GF(f2)) = F(f1) & GF(f2) - // - // As is, these two formulae are translated into - // equivalent Büchi automata so the rewriting is - // useless. - // - // However when taken in a larger formula such - // as F(f1 & GF(f2)) | F(a & GF(b)), this - // rewriting used to produce (F(f1) & GF(f2)) | - // (F(a) & GF(b)), missing the opportunity to - // apply the F(E1)|F(E2) = F(E1|E2) rule which - // really helps the translation. F((f1 & GF(f2)) - // | (a & GF(b))) is indeed easier to translate. - // - // So we do not consider this rewriting rule by - // default. However if favor_event_univ is set, - // we want to move the GF out of the F. - if (opt_.favor_event_univ) - // F(f1&f2&FG(f3)&FG(f4)&f5&f6) = - // F(f1&f2) & FG(f3&f4) & f5 & f6 - // if f5 and f6 are both eventual and universal. - if (c.is(op::And)) - { - mospliter s(mospliter::Strip_FG | - mospliter::Split_EventUniv, - c, c_); - s.res_EventUniv-> - push_back(unop_multop(op::F, op::And, - std::move(*s.res_other))); - s.res_EventUniv-> - push_back(unop_unop_multop(op::F, op::G, op::And, - std::move(*s.res_FG))); - formula res = - formula::And(std::move(*s.res_EventUniv)); - if (res != f) - return recurse(res); - } - // If u3 and u4 are universal formulae and h is not: - // F(f1 | f2 | Fu3 | u4 | FGg | Fh) - // = F(f1 | f2 | u3 | u4 | Gg | h) - // or - // F(f1 | f2 | Fu3 | u4 | FGg | Fh) - // = F(f1 | f2 | h) | F(u3 | u4 | Gg) - // depending on whether favor_event_univ is set. - if (c.is(op::Or)) - { - int w = mospliter::Strip_F; - if (opt_.favor_event_univ) - w |= mospliter::Split_Univ; - mospliter s(w, c, c_); - s.res_other->insert(s.res_other->end(), - s.res_F->begin(), s.res_F->end()); - formula res = unop_multop(op::F, op::Or, - std::move(*s.res_other)); - if (s.res_Univ) - { - // Strip any F. - for (auto& g: *s.res_Univ) - if (g.is(op::F)) - g = g[0]; - formula fu = unop_multop(op::F, op::Or, - std::move(*s.res_Univ)); - res = formula::Or({res, fu}); - } - if (res != f) - return recurse(res); - } - } - return f; - case op::G: - { - formula c = f[0]; - // If f is a pure universality formula then G(f)=f. - if (opt_.event_univ && c.is_universal()) - return c; + // Disabled by default: + // F(f1 & GF(f2)) = F(f1) & GF(f2) + // + // As is, these two formulae are translated into + // equivalent Büchi automata so the rewriting is + // useless. + // + // However when taken in a larger formula such + // as F(f1 & GF(f2)) | F(a & GF(b)), this + // rewriting used to produce (F(f1) & GF(f2)) | + // (F(a) & GF(b)), missing the opportunity to + // apply the F(E1)|F(E2) = F(E1|E2) rule which + // really helps the translation. F((f1 & GF(f2)) + // | (a & GF(b))) is indeed easier to translate. + // + // So we do not consider this rewriting rule by + // default. However if favor_event_univ is set, + // we want to move the GF out of the F. + if (opt_.favor_event_univ) + // F(f1&f2&FG(f3)&FG(f4)&f5&f6) = + // F(f1&f2) & FG(f3&f4) & f5 & f6 + // if f5 and f6 are both eventual and universal. + if (c.is(op::And)) + { + mospliter s(mospliter::Strip_FG | + mospliter::Split_EventUniv, + c, c_); + s.res_EventUniv-> + push_back(unop_multop(op::F, op::And, + std::move(*s.res_other))); + s.res_EventUniv-> + push_back(unop_unop_multop(op::F, op::G, op::And, + std::move(*s.res_FG))); + formula res = + formula::And(std::move(*s.res_EventUniv)); + if (res != f) + return recurse(res); + } + // If u3 and u4 are universal formulae and h is not: + // F(f1 | f2 | Fu3 | u4 | FGg | Fh) + // = F(f1 | f2 | u3 | u4 | Gg | h) + // or + // F(f1 | f2 | Fu3 | u4 | FGg | Fh) + // = F(f1 | f2 | h) | F(u3 | u4 | Gg) + // depending on whether favor_event_univ is set. + if (c.is(op::Or)) + { + int w = mospliter::Strip_F; + if (opt_.favor_event_univ) + w |= mospliter::Split_Univ; + mospliter s(w, c, c_); + s.res_other->insert(s.res_other->end(), + s.res_F->begin(), s.res_F->end()); + formula res = unop_multop(op::F, op::Or, + std::move(*s.res_other)); + if (s.res_Univ) + { + // Strip any F. + for (auto& g: *s.res_Univ) + if (g.is(op::F)) + g = g[0]; + formula fu = unop_multop(op::F, op::Or, + std::move(*s.res_Univ)); + res = formula::Or({res, fu}); + } + if (res != f) + return recurse(res); + } + } + return f; + case op::G: + { + formula c = f[0]; + // If f is a pure universality formula then G(f)=f. + if (opt_.event_univ && c.is_universal()) + return c; - if (opt_.reduce_basics) - { - // G(a R b) = G(b) - if (c.is(op::R)) - return recurse(formula::G(c[1])); + if (opt_.reduce_basics) + { + // G(a R b) = G(b) + if (c.is(op::R)) + return recurse(formula::G(c[1])); - // G(a W b) = G(a | b) - if (c.is(op::W)) - return recurse(unop_multop(op::G, op::Or, - {c[0], c[1]})); + // G(a W b) = G(a | b) + if (c.is(op::W)) + return recurse(unop_multop(op::G, op::Or, + {c[0], c[1]})); - // GX(a) = XG(a) - // GXX(a) = XXG(a) ... - // GXF(a) = XGF(a) = GF(a) ... - if (c.is(op::X)) - return recurse(unop_unop(op::X, op::G, c[0])); + // GX(a) = XG(a) + // GXX(a) = XXG(a) ... + // GXF(a) = XGF(a) = GF(a) ... + if (c.is(op::X)) + return recurse(unop_unop(op::X, op::G, c[0])); - // G(f1|f2|GF(f3)|GF(f4)|f5|f6) = - // G(f1|f2) | GF(f3|f4) | f5 | f6 - // if f5 and f6 are both eventual and universal. - if (c.is(op::Or)) - { - mospliter s(mospliter::Strip_GF | - mospliter::Split_EventUniv, - c, c_); - s.res_EventUniv-> - push_back(unop_multop(op::G, op::Or, - std::move(*s.res_other))); - s.res_EventUniv-> - push_back(unop_unop_multop(op::G, op::F, op::Or, - std::move(*s.res_GF))); - formula res = - formula::Or(std::move(*s.res_EventUniv)); + // G(f1|f2|GF(f3)|GF(f4)|f5|f6) = + // G(f1|f2) | GF(f3|f4) | f5 | f6 + // if f5 and f6 are both eventual and universal. + if (c.is(op::Or)) + { + mospliter s(mospliter::Strip_GF | + mospliter::Split_EventUniv, + c, c_); + s.res_EventUniv-> + push_back(unop_multop(op::G, op::Or, + std::move(*s.res_other))); + s.res_EventUniv-> + push_back(unop_unop_multop(op::G, op::F, op::Or, + std::move(*s.res_GF))); + formula res = + formula::Or(std::move(*s.res_EventUniv)); - if (res != f) - return recurse(res); - } - // If e3 and e4 are eventual formulae and h is not: - // G(f1 & f2 & Ge3 & e4 & GFg & Gh) - // = G(f1 & f2 & e3 & e4 & Fg & h) - // or - // G(f1 & f2 & Ge3 & e4 & GFg & Gh) - // = G(f1 & f2 & h) & G(e3 & e4 & Fg) - // depending on whether favor_event_univ is set. - else if (c.is(op::And)) - { - int w = mospliter::Strip_G; - if (opt_.favor_event_univ) - w |= mospliter::Split_Event; - mospliter s(w, c, c_); - s.res_other->insert(s.res_other->end(), - s.res_G->begin(), s.res_G->end()); - formula res = unop_multop(op::G, op::And, - std::move(*s.res_other)); + if (res != f) + return recurse(res); + } + // If e3 and e4 are eventual formulae and h is not: + // G(f1 & f2 & Ge3 & e4 & GFg & Gh) + // = G(f1 & f2 & e3 & e4 & Fg & h) + // or + // G(f1 & f2 & Ge3 & e4 & GFg & Gh) + // = G(f1 & f2 & h) & G(e3 & e4 & Fg) + // depending on whether favor_event_univ is set. + else if (c.is(op::And)) + { + int w = mospliter::Strip_G; + if (opt_.favor_event_univ) + w |= mospliter::Split_Event; + mospliter s(w, c, c_); + s.res_other->insert(s.res_other->end(), + s.res_G->begin(), s.res_G->end()); + formula res = unop_multop(op::G, op::And, + std::move(*s.res_other)); - if (s.res_Event) - { - // Strip any G. - for (auto& g: *s.res_Event) - if (g.is(op::G)) - g = g[0]; - formula ge = - unop_multop(op::G, op::And, - std::move(*s.res_Event)); - res = formula::And({res, ge}); - } - if (res != f) - return recurse(res); - } + if (s.res_Event) + { + // Strip any G. + for (auto& g: *s.res_Event) + if (g.is(op::G)) + g = g[0]; + formula ge = + unop_multop(op::G, op::And, + std::move(*s.res_Event)); + res = formula::And({res, ge}); + } + if (res != f) + return recurse(res); + } - // GF(a | Xb) = GF(a | b) - // GF(a | Fb) = GF(a | b) - if (c.is({op::F, op::Or})) - { - formula m = c[0]; - if (!m.is_boolean()) - { - formula out = m.map([](formula f) - { - if (f.is(op::X, op::F)) - return f[0]; - return f; - }); - if (out != m) - return recurse(unop_unop(op::G, op::F, out)); - } - } - } - // if a => Ga, keep a. - if (opt_.containment_checks_stronger - && c_->lcc.contained(c, f)) - return c; - } - return f; - case op::Closure: - case op::NegClosure: - case op::NegClosureMarked: - { - formula c = f[0]; - // {e[*]} = {e} - // !{e[*]} = !{e} - if (c.accepts_eword() && c.is(op::Star)) - return recurse(formula::unop(o, c[0])); + // GF(a | Xb) = GF(a | b) + // GF(a | Fb) = GF(a | b) + if (c.is({op::F, op::Or})) + { + formula m = c[0]; + if (!m.is_boolean()) + { + formula out = m.map([](formula f) + { + if (f.is(op::X, op::F)) + return f[0]; + return f; + }); + if (out != m) + return recurse(unop_unop(op::G, op::F, out)); + } + } + } + // if a => Ga, keep a. + if (opt_.containment_checks_stronger + && c_->lcc.contained(c, f)) + return c; + } + return f; + case op::Closure: + case op::NegClosure: + case op::NegClosureMarked: + { + formula c = f[0]; + // {e[*]} = {e} + // !{e[*]} = !{e} + if (c.accepts_eword() && c.is(op::Star)) + return recurse(formula::unop(o, c[0])); - if (!opt_.reduce_size_strictly) - if (c.is(op::OrRat)) - { - // {a₁|a₂} = {a₁}| {a₂} - // !{a₁|a₂} = !{a₁}&!{a₂} - unsigned s = c.size(); - vec v; - for (unsigned n = 0; n < s; ++n) - v.push_back(formula::unop(o, c[n])); - return recurse(formula::multop(o == op::Closure - ? op::Or : op::And, v)); - } - if (c.is(op::Concat)) - { - if (c.accepts_eword()) - { - if (opt_.reduce_size_strictly) - return f; - // If all terms accept the empty word, we have - // {e₁;e₂;e₃} = {e₁}|{e₂}|{e₃} - // !{e₁;e₂;e₃} = !{e₁}&!{e₂}&!{e₃} - vec v; - unsigned end = c.size(); - v.reserve(end); - for (unsigned i = 0; i < end; ++i) - v.push_back(formula::unop(o, c[i])); - return recurse(formula::multop(o == op::Closure ? - op::Or : op::And, v)); - } + if (!opt_.reduce_size_strictly) + if (c.is(op::OrRat)) + { + // {a₁|a₂} = {a₁}| {a₂} + // !{a₁|a₂} = !{a₁}&!{a₂} + unsigned s = c.size(); + vec v; + for (unsigned n = 0; n < s; ++n) + v.push_back(formula::unop(o, c[n])); + return recurse(formula::multop(o == op::Closure + ? op::Or : op::And, v)); + } + if (c.is(op::Concat)) + { + if (c.accepts_eword()) + { + if (opt_.reduce_size_strictly) + return f; + // If all terms accept the empty word, we have + // {e₁;e₂;e₃} = {e₁}|{e₂}|{e₃} + // !{e₁;e₂;e₃} = !{e₁}&!{e₂}&!{e₃} + vec v; + unsigned end = c.size(); + v.reserve(end); + for (unsigned i = 0; i < end; ++i) + v.push_back(formula::unop(o, c[i])); + return recurse(formula::multop(o == op::Closure ? + op::Or : op::And, v)); + } - // Some term does not accept the empty word. - unsigned end = c.size() - 1; - // {b₁;b₂;e₁;f₁;e₂;f₂;e₂;e₃;e₄} - // = b₁&X(b₂&X({e₁;f₁;e₂;f₂})) - // !{b₁;b₂;e₁;f₁;e₂;f₂;e₂;e₃;e₄} - // = !b₁|X(!b₂|X(!{e₁;f₁;e₂;f₂})) - // if e denotes a term that accepts [*0] - // and b denotes a Boolean formula. - while (c[end].accepts_eword()) - --end; - unsigned start = 0; - while (start <= end) - { - formula r = c[start]; - if (r.is_boolean() && !opt_.reduce_size_strictly) - ++start; - else - break; - } - unsigned s = end + 1 - start; - if (s != c.size()) - { - bool doneg = o != op::Closure; - formula tail; - if (s > 0) - { - vec v; - v.reserve(s); - for (unsigned n = start; n <= end; ++n) - v.push_back(c[n]); - tail = formula::Concat(v); - tail = formula::unop(o, tail); - } - else - { - tail = doneg ? formula::ff() : formula::tt(); - } + // Some term does not accept the empty word. + unsigned end = c.size() - 1; + // {b₁;b₂;e₁;f₁;e₂;f₂;e₂;e₃;e₄} + // = b₁&X(b₂&X({e₁;f₁;e₂;f₂})) + // !{b₁;b₂;e₁;f₁;e₂;f₂;e₂;e₃;e₄} + // = !b₁|X(!b₂|X(!{e₁;f₁;e₂;f₂})) + // if e denotes a term that accepts [*0] + // and b denotes a Boolean formula. + while (c[end].accepts_eword()) + --end; + unsigned start = 0; + while (start <= end) + { + formula r = c[start]; + if (r.is_boolean() && !opt_.reduce_size_strictly) + ++start; + else + break; + } + unsigned s = end + 1 - start; + if (s != c.size()) + { + bool doneg = o != op::Closure; + formula tail; + if (s > 0) + { + vec v; + v.reserve(s); + for (unsigned n = start; n <= end; ++n) + v.push_back(c[n]); + tail = formula::Concat(v); + tail = formula::unop(o, tail); + } + else + { + tail = doneg ? formula::ff() : formula::tt(); + } - for (unsigned n = start; n > 0;) - { - --n; - formula e = c[n]; - // {b;f} = b & X{f} - // !{b;f} = !b | X!{f} - if (e.is_boolean()) - { - tail = formula::X(tail); - if (doneg) - tail = formula::Or({formula::Not(e), tail}); - else - tail = formula::And({e, tail}); - } - } - return recurse(tail); - } + for (unsigned n = start; n > 0;) + { + --n; + formula e = c[n]; + // {b;f} = b & X{f} + // !{b;f} = !b | X!{f} + if (e.is_boolean()) + { + tail = formula::X(tail); + if (doneg) + tail = formula::Or({formula::Not(e), tail}); + else + tail = formula::And({e, tail}); + } + } + return recurse(tail); + } - // {b[*i..j];c} = b&X(b&X(... b&X{b[*0..j-i];c})) - // !{b[*i..j];c} = !b&X(!b&X(... !b&X!{b[*0..j-i];c})) - if (!opt_.reduce_size_strictly) - if (c[0].is(op::Star)) - { - formula s = c[0]; - formula sc = s[0]; - unsigned min = s.min(); - if (sc.is_boolean() && min > 0) - { - unsigned max = s.max(); - if (max != formula::unbounded()) - max -= min; - unsigned ss = c.size(); - vec v; - v.reserve(ss); - v.push_back(formula::Star(sc, 0, max)); - for (unsigned n = 1; n < ss; ++n) - v.push_back(c[n]); - formula tail = formula::Concat(v); - tail = // {b[*0..j-i]} or !{b[*0..j-i]} - formula::unop(o, tail); - tail = - dup_b_x_tail(o != op::Closure, - sc, tail, min); - return recurse(tail); - } - } - } - // {b[*i..j]} = b&X(b&X(... b)) with i occurences of b - // !{b[*i..j]} = !b&X(!b&X(... !b)) - if (!opt_.reduce_size_strictly) - if (c.is(op::Star)) - { - formula cs = c[0]; - if (cs.is_boolean()) - { - unsigned min = c.min(); - assert(min > 0); - formula tail; - if (o == op::Closure) - tail = dup_b_x_tail(false, cs, - formula::tt(), min); - else - tail = dup_b_x_tail(true, cs, - formula::ff(), min); - return recurse(tail); - } - } - return f; - } - case op::Xor: - case op::Implies: - case op::Equiv: - case op::U: - case op::R: - case op::W: - case op::M: - case op::EConcat: - case op::EConcatMarked: - case op::UConcat: - return visit_binop(f); - case op::Or: - case op::OrRat: - case op::And: - case op::AndRat: - case op::AndNLM: - case op::Concat: - return visit_multop(f); - case op::Fusion: - return f; - case op::Star: - { - formula h = f[0]; - auto min = f.min(); - if (h.accepts_eword()) - min = 0; - if (min == 0) - h = f.max() == formula::unbounded() - ? c_->star_normal_form(h) - : c_->star_normal_form_bounded(h); - return formula::Star(h, min, f.max()); - } - } - SPOT_UNREACHABLE(); + // {b[*i..j];c} = b&X(b&X(... b&X{b[*0..j-i];c})) + // !{b[*i..j];c} = !b&X(!b&X(... !b&X!{b[*0..j-i];c})) + if (!opt_.reduce_size_strictly) + if (c[0].is(op::Star)) + { + formula s = c[0]; + formula sc = s[0]; + unsigned min = s.min(); + if (sc.is_boolean() && min > 0) + { + unsigned max = s.max(); + if (max != formula::unbounded()) + max -= min; + unsigned ss = c.size(); + vec v; + v.reserve(ss); + v.push_back(formula::Star(sc, 0, max)); + for (unsigned n = 1; n < ss; ++n) + v.push_back(c[n]); + formula tail = formula::Concat(v); + tail = // {b[*0..j-i]} or !{b[*0..j-i]} + formula::unop(o, tail); + tail = + dup_b_x_tail(o != op::Closure, + sc, tail, min); + return recurse(tail); + } + } + } + // {b[*i..j]} = b&X(b&X(... b)) with i occurences of b + // !{b[*i..j]} = !b&X(!b&X(... !b)) + if (!opt_.reduce_size_strictly) + if (c.is(op::Star)) + { + formula cs = c[0]; + if (cs.is_boolean()) + { + unsigned min = c.min(); + assert(min > 0); + formula tail; + if (o == op::Closure) + tail = dup_b_x_tail(false, cs, + formula::tt(), min); + else + tail = dup_b_x_tail(true, cs, + formula::ff(), min); + return recurse(tail); + } + } + return f; + } + case op::Xor: + case op::Implies: + case op::Equiv: + case op::U: + case op::R: + case op::W: + case op::M: + case op::EConcat: + case op::EConcatMarked: + case op::UConcat: + return visit_binop(f); + case op::Or: + case op::OrRat: + case op::And: + case op::AndRat: + case op::AndNLM: + case op::Concat: + return visit_multop(f); + case op::Fusion: + return f; + case op::Star: + { + formula h = f[0]; + auto min = f.min(); + if (h.accepts_eword()) + min = 0; + if (min == 0) + h = f.max() == formula::unbounded() + ? c_->star_normal_form(h) + : c_->star_normal_form_bounded(h); + return formula::Star(h, min, f.max()); + } + } + SPOT_UNREACHABLE(); } formula reduce_sere_ltl(formula orig) { - op bindop = orig.kind(); - formula a = orig[0]; - formula b = orig[1]; + op bindop = orig.kind(); + formula a = orig[0]; + formula b = orig[1]; - auto recurse = [this](formula f) - { - return simplify_recursively(f, c_); - }; + auto recurse = [this](formula f) + { + return simplify_recursively(f, c_); + }; - // All this function is documented assuming bindop == - // UConcat, but by changing the following variables it can - // perform the rules for EConcat as well. - op op_g; - op op_w; - op op_r; - op op_and; - bool doneg; - if (bindop == op::UConcat) - { - op_g = op::G; - op_w = op::W; - op_r = op::R; - op_and = op::And; - doneg = true; - } - else // EConcat & EConcatMarked - { - op_g = op::F; - op_w = op::M; - op_r = op::U; - op_and = op::Or; - doneg = false; - } + // All this function is documented assuming bindop == + // UConcat, but by changing the following variables it can + // perform the rules for EConcat as well. + op op_g; + op op_w; + op op_r; + op op_and; + bool doneg; + if (bindop == op::UConcat) + { + op_g = op::G; + op_w = op::W; + op_r = op::R; + op_and = op::And; + doneg = true; + } + else // EConcat & EConcatMarked + { + op_g = op::F; + op_w = op::M; + op_r = op::U; + op_and = op::Or; + doneg = false; + } - if (!opt_.reduce_basics) - return orig; - if (a.is(op::Star)) - { - // {[*]}[]->b = Gb - if (a == formula::one_star()) - return recurse(formula::unop(op_g, b)); + if (!opt_.reduce_basics) + return orig; + if (a.is(op::Star)) + { + // {[*]}[]->b = Gb + if (a == formula::one_star()) + return recurse(formula::unop(op_g, b)); - formula s = a[0]; - unsigned min = a.min(); - unsigned max = a.max(); - // {s[*]}[]->b = b W !s if s is Boolean. - // {s[+]}[]->b = b W !s if s is Boolean. - if (s.is_boolean() && max == formula::unbounded() && min <= 1) - { - formula ns = doneg ? formula::Not(s) : s; - // b W !s - return recurse(formula::binop(op_w, b, ns)); - } - if (opt_.reduce_size_strictly) - return orig; - // {s[*i..j]}[]->b = {s;s;...;s[*1..j-i+1]}[]->b - // = {s}[]->X({s}[]->X(...[]->X({s[*1..j-i+1]}[]->b))) - // if i>0 and s does not accept the empty word - if (min == 0 || s.accepts_eword()) - return orig; - --min; - if (max != formula::unbounded()) - max -= min; // j-i+1 - // Don't rewrite s[1..]. - if (min == 0) - return orig; - formula tail = // {s[*1..j-i]}[]->b - formula::binop(bindop, formula::Star(s, 1, max), b); - for (unsigned n = 0; n < min; ++n) - tail = // {s}[]->X(tail) - formula::binop(bindop, s, formula::X(tail)); - return recurse(tail); - } - else if (a.is(op::Concat)) - { - unsigned s = a.size() - 1; - formula last = a[s]; - // {r;[*]}[]->b = {r}[]->Gb - if (last == formula::one_star()) - return recurse(formula::binop(bindop, a.all_but(s), - formula::unop(op_g, b))); + formula s = a[0]; + unsigned min = a.min(); + unsigned max = a.max(); + // {s[*]}[]->b = b W !s if s is Boolean. + // {s[+]}[]->b = b W !s if s is Boolean. + if (s.is_boolean() && max == formula::unbounded() && min <= 1) + { + formula ns = doneg ? formula::Not(s) : s; + // b W !s + return recurse(formula::binop(op_w, b, ns)); + } + if (opt_.reduce_size_strictly) + return orig; + // {s[*i..j]}[]->b = {s;s;...;s[*1..j-i+1]}[]->b + // = {s}[]->X({s}[]->X(...[]->X({s[*1..j-i+1]}[]->b))) + // if i>0 and s does not accept the empty word + if (min == 0 || s.accepts_eword()) + return orig; + --min; + if (max != formula::unbounded()) + max -= min; // j-i+1 + // Don't rewrite s[1..]. + if (min == 0) + return orig; + formula tail = // {s[*1..j-i]}[]->b + formula::binop(bindop, formula::Star(s, 1, max), b); + for (unsigned n = 0; n < min; ++n) + tail = // {s}[]->X(tail) + formula::binop(bindop, s, formula::X(tail)); + return recurse(tail); + } + else if (a.is(op::Concat)) + { + unsigned s = a.size() - 1; + formula last = a[s]; + // {r;[*]}[]->b = {r}[]->Gb + if (last == formula::one_star()) + return recurse(formula::binop(bindop, a.all_but(s), + formula::unop(op_g, b))); - formula first = a[0]; - // {[*];r}[]->b = G({r}[]->b) - if (first == formula::one_star()) - return recurse(formula::unop(op_g, - formula::binop(bindop, - a.all_but(0), b))); + formula first = a[0]; + // {[*];r}[]->b = G({r}[]->b) + if (first == formula::one_star()) + return recurse(formula::unop(op_g, + formula::binop(bindop, + a.all_but(0), b))); - if (opt_.reduce_size_strictly) - return orig; + if (opt_.reduce_size_strictly) + return orig; - // {r;s[*]}[]->b = {r}[]->(b & X(b W !s)) - // if s is Boolean and r does not accept [*0]; - if (last.is_Kleene_star()) // l = s[*] - if (last[0].is_boolean()) - { - formula r = a.all_but(s); - if (!r.accepts_eword()) - { - formula ns = // !s - doneg ? formula::Not(last[0]) : last[0]; - formula w = // b W !s - formula::binop(op_w, b, ns); - formula x = // X(b W !s) - formula::X(w); - formula d = // b & X(b W !s) - formula::multop(op_and, {b, x}); - // {r}[]->(b & X(b W !s)) - return recurse(formula::binop(bindop, r, d)); - } - } - // {s[*];r}[]->b = !s R ({r}[]->b) - // if s is Boolean and r does not accept [*0]; - if (first.is_Kleene_star()) - if (first[0].is_boolean()) - { - formula r = a.all_but(0); - if (!r.accepts_eword()) - { - formula ns = // !s - doneg - ? formula::Not(first[0]) - : first[0]; - formula u = // {r}[]->b - formula::binop(bindop, r, b); - // !s R ({r}[]->b) - return recurse(formula::binop(op_r, ns, u)); - } - } + // {r;s[*]}[]->b = {r}[]->(b & X(b W !s)) + // if s is Boolean and r does not accept [*0]; + if (last.is_Kleene_star()) // l = s[*] + if (last[0].is_boolean()) + { + formula r = a.all_but(s); + if (!r.accepts_eword()) + { + formula ns = // !s + doneg ? formula::Not(last[0]) : last[0]; + formula w = // b W !s + formula::binop(op_w, b, ns); + formula x = // X(b W !s) + formula::X(w); + formula d = // b & X(b W !s) + formula::multop(op_and, {b, x}); + // {r}[]->(b & X(b W !s)) + return recurse(formula::binop(bindop, r, d)); + } + } + // {s[*];r}[]->b = !s R ({r}[]->b) + // if s is Boolean and r does not accept [*0]; + if (first.is_Kleene_star()) + if (first[0].is_boolean()) + { + formula r = a.all_but(0); + if (!r.accepts_eword()) + { + formula ns = // !s + doneg + ? formula::Not(first[0]) + : first[0]; + formula u = // {r}[]->b + formula::binop(bindop, r, b); + // !s R ({r}[]->b) + return recurse(formula::binop(op_r, ns, u)); + } + } - // {r₁;r₂;r₃}[]->b = {r₁}[]->X({r₂}[]->X({r₃}[]->b)) - // if r₁, r₂, r₃ do not accept [*0]. - if (!a.accepts_eword()) - { - unsigned count = 0; - for (unsigned n = 0; n <= s; ++n) - count += !a[n].accepts_eword(); - assert(count > 0); - if (count == 1) - return orig; - // Let e denote a term that accepts [*0] - // and let f denote a term that do not. - // A formula such as {e₁;f₁;e₂;e₃;f₂;e₄}[]->b - // in which count==2 will be grouped - // as follows: r₁ = e₁;f₁;e₂;e₃ - // r₂ = f₂;e₄ - // this way we have - // {e₁;f₁;e₂;e₃;f₂;e₄}[]->b = {r₁;r₂;r₃}[]->b - // where r₁ and r₂ do not accept [*0]. - unsigned pos = s + 1; + // {r₁;r₂;r₃}[]->b = {r₁}[]->X({r₂}[]->X({r₃}[]->b)) + // if r₁, r₂, r₃ do not accept [*0]. + if (!a.accepts_eword()) + { + unsigned count = 0; + for (unsigned n = 0; n <= s; ++n) + count += !a[n].accepts_eword(); + assert(count > 0); + if (count == 1) + return orig; + // Let e denote a term that accepts [*0] + // and let f denote a term that do not. + // A formula such as {e₁;f₁;e₂;e₃;f₂;e₄}[]->b + // in which count==2 will be grouped + // as follows: r₁ = e₁;f₁;e₂;e₃ + // r₂ = f₂;e₄ + // this way we have + // {e₁;f₁;e₂;e₃;f₂;e₄}[]->b = {r₁;r₂;r₃}[]->b + // where r₁ and r₂ do not accept [*0]. + unsigned pos = s + 1; - // We compute the r formulas from the right - // (i.e., r₂ before r₁.) - vec r; - do - r.insert(r.begin(), a[--pos]); - while (r.front().accepts_eword()); - formula tail = // {r₂}[]->b - formula::binop(bindop, formula::Concat(r), b); - while (--count) - { - vec r; - do - r.insert(r.begin(), a[--pos]); - while (r.front().accepts_eword()); - // If it's the last block, take all leading - // formulae as well. - if (count == 1) - while (pos > 0) - { - r.insert(r.begin(), a[--pos]); - assert(r.front().accepts_eword()); - } + // We compute the r formulas from the right + // (i.e., r₂ before r₁.) + vec r; + do + r.insert(r.begin(), a[--pos]); + while (r.front().accepts_eword()); + formula tail = // {r₂}[]->b + formula::binop(bindop, formula::Concat(r), b); + while (--count) + { + vec r; + do + r.insert(r.begin(), a[--pos]); + while (r.front().accepts_eword()); + // If it's the last block, take all leading + // formulae as well. + if (count == 1) + while (pos > 0) + { + r.insert(r.begin(), a[--pos]); + assert(r.front().accepts_eword()); + } - tail = // X({r₂}[]->b) - formula::X(tail); - tail = // {r₁}[]->X({r₂}[]->b) - formula::binop(bindop, formula::Concat(r), tail); - } - return recurse(tail); - } - } - else if (opt_.reduce_size_strictly) - { - return orig; - } - else if (a.is(op::Fusion)) - { - // {r₁:r₂:r₃}[]->b = {r₁}[]->({r₂}[]->({r₃}[]->b)) - unsigned s = a.size(); - formula tail = b; - do - { - --s; - tail = formula::binop(bindop, a[s], tail); - } - while (s != 0); - return recurse(tail); - } - else if (a.is(op::OrRat)) - { - // {r₁|r₂|r₃}[]->b = ({r₁}[]->b)&({r₂}[]->b)&({r₃}[]->b) - unsigned s = a.size(); - vec v; - for (unsigned n = 0; n < s; ++n) - // {r₁}[]->b - v.push_back(formula::binop(bindop, a[n], b)); - return recurse(formula::multop(op_and, v)); - } - return orig; + tail = // X({r₂}[]->b) + formula::X(tail); + tail = // {r₁}[]->X({r₂}[]->b) + formula::binop(bindop, formula::Concat(r), tail); + } + return recurse(tail); + } + } + else if (opt_.reduce_size_strictly) + { + return orig; + } + else if (a.is(op::Fusion)) + { + // {r₁:r₂:r₃}[]->b = {r₁}[]->({r₂}[]->({r₃}[]->b)) + unsigned s = a.size(); + formula tail = b; + do + { + --s; + tail = formula::binop(bindop, a[s], tail); + } + while (s != 0); + return recurse(tail); + } + else if (a.is(op::OrRat)) + { + // {r₁|r₂|r₃}[]->b = ({r₁}[]->b)&({r₂}[]->b)&({r₃}[]->b) + unsigned s = a.size(); + vec v; + for (unsigned n = 0; n < s; ++n) + // {r₁}[]->b + v.push_back(formula::binop(bindop, a[n], b)); + return recurse(formula::multop(op_and, v)); + } + return orig; } formula - visit_binop(formula bo) + visit_binop(formula bo) { - auto recurse = [this](formula f) - { - return simplify_recursively(f, c_); - }; - op o = bo.kind(); - formula b = bo[1]; - if (opt_.event_univ) - { - trace << "bo: trying eventuniv rules" << std::endl; - /* If b is a pure eventuality formula then a U b = b. - If b is a pure universality formula a R b = b. */ - if ((b.is_eventual() && bo.is(op::U)) - || (b.is_universal() && bo.is(op::R))) - return b; - } + auto recurse = [this](formula f) + { + return simplify_recursively(f, c_); + }; + op o = bo.kind(); + formula b = bo[1]; + if (opt_.event_univ) + { + trace << "bo: trying eventuniv rules" << std::endl; + /* If b is a pure eventuality formula then a U b = b. + If b is a pure universality formula a R b = b. */ + if ((b.is_eventual() && bo.is(op::U)) + || (b.is_universal() && bo.is(op::R))) + return b; + } - formula a = bo[0]; - if (opt_.event_univ) - { - /* If a is a pure eventuality formula then a M b = a & b. - If a is a pure universality formula a W b = a | b. */ - if (a.is_eventual() && bo.is(op::M)) - return recurse(formula::And({a, b})); - if (a.is_universal() && bo.is(op::W)) - return recurse(formula::Or({a, b})); + formula a = bo[0]; + if (opt_.event_univ) + { + /* If a is a pure eventuality formula then a M b = a & b. + If a is a pure universality formula a W b = a | b. */ + if (a.is_eventual() && bo.is(op::M)) + return recurse(formula::And({a, b})); + if (a.is_universal() && bo.is(op::W)) + return recurse(formula::Or({a, b})); - // e₁ W e₂ = Ge₁ | e₂ - // u₁ M u₂ = Fu₁ & u₂ - if (!opt_.reduce_size_strictly) - { - if (bo.is(op::W) && a.is_eventual() && b.is_eventual()) - return recurse(formula::Or({formula::G(a), b})); - if (bo.is(op::M) && a.is_universal() && b.is_universal()) - return recurse(formula::And({formula::F(a), b})); - } + // e₁ W e₂ = Ge₁ | e₂ + // u₁ M u₂ = Fu₁ & u₂ + if (!opt_.reduce_size_strictly) + { + if (bo.is(op::W) && a.is_eventual() && b.is_eventual()) + return recurse(formula::Or({formula::G(a), b})); + if (bo.is(op::M) && a.is_universal() && b.is_universal()) + return recurse(formula::And({formula::F(a), b})); + } - // In the following rewritings we assume that - // - e is a pure eventuality - // - u is purely universal - // - q is purely universal pure eventuality - // (a U (b|e)) = (a U b)|e - // (a W (b|e)) = (a W b)|e - // (a U (b&q)) = (a U b)&q - // ((a&q) M b) = (a M b)&q - // (a R (b&u)) = (a R b)&u - // (a M (b&u)) = (a M b)&u - if (opt_.favor_event_univ) - { - if (bo.is(op::U, op::W)) - if (b.is(op::Or)) - { - mospliter s(mospliter::Split_Event, b, c_); - formula b2 = formula::Or(std::move(*s.res_other)); - if (b2 != b) - { - s.res_Event->push_back(formula::binop(o, a, b2)); - return recurse - (formula::Or(std::move(*s.res_Event))); - } - } - if (bo.is(op::U)) - if (b.is(op::And)) - { - mospliter s(mospliter::Split_EventUniv, b, c_); - formula b2 = formula::And(std::move(*s.res_other)); - if (b2 != b) - { - s.res_EventUniv->push_back(formula::binop(o, - a, b2)); - return recurse - (formula::And(std::move(*s.res_EventUniv))); - } - } - if (bo.is(op::M)) - if (a.is(op::And)) - { - mospliter s(mospliter::Split_EventUniv, a, c_); - formula a2 = formula::And(std::move(*s.res_other)); - if (a2 != a) - { - s.res_EventUniv->push_back(formula::binop(o, - a2, b)); - return recurse - (formula::And(std::move(*s.res_EventUniv))); - } - } - if (bo.is(op::R, op::M)) - if (b.is(op::And)) - { - mospliter s(mospliter::Split_Univ, b, c_); - formula b2 = formula::And(std::move(*s.res_other)); - if (b2 != b) - { - s.res_Univ->push_back(formula::binop(o, a, b2)); - return recurse - (formula::And(std::move(*s.res_Univ))); - } - } - } - trace << "bo: no eventuniv rule matched" << std::endl; - } + // In the following rewritings we assume that + // - e is a pure eventuality + // - u is purely universal + // - q is purely universal pure eventuality + // (a U (b|e)) = (a U b)|e + // (a W (b|e)) = (a W b)|e + // (a U (b&q)) = (a U b)&q + // ((a&q) M b) = (a M b)&q + // (a R (b&u)) = (a R b)&u + // (a M (b&u)) = (a M b)&u + if (opt_.favor_event_univ) + { + if (bo.is(op::U, op::W)) + if (b.is(op::Or)) + { + mospliter s(mospliter::Split_Event, b, c_); + formula b2 = formula::Or(std::move(*s.res_other)); + if (b2 != b) + { + s.res_Event->push_back(formula::binop(o, a, b2)); + return recurse + (formula::Or(std::move(*s.res_Event))); + } + } + if (bo.is(op::U)) + if (b.is(op::And)) + { + mospliter s(mospliter::Split_EventUniv, b, c_); + formula b2 = formula::And(std::move(*s.res_other)); + if (b2 != b) + { + s.res_EventUniv->push_back(formula::binop(o, + a, b2)); + return recurse + (formula::And(std::move(*s.res_EventUniv))); + } + } + if (bo.is(op::M)) + if (a.is(op::And)) + { + mospliter s(mospliter::Split_EventUniv, a, c_); + formula a2 = formula::And(std::move(*s.res_other)); + if (a2 != a) + { + s.res_EventUniv->push_back(formula::binop(o, + a2, b)); + return recurse + (formula::And(std::move(*s.res_EventUniv))); + } + } + if (bo.is(op::R, op::M)) + if (b.is(op::And)) + { + mospliter s(mospliter::Split_Univ, b, c_); + formula b2 = formula::And(std::move(*s.res_other)); + if (b2 != b) + { + s.res_Univ->push_back(formula::binop(o, a, b2)); + return recurse + (formula::And(std::move(*s.res_Univ))); + } + } + } + trace << "bo: no eventuniv rule matched" << std::endl; + } - // Inclusion-based rules - if (opt_.synt_impl | opt_.containment_checks) - { - trace << "bo: trying inclusion-based rules" << std::endl; - switch (o) - { - case op::Xor: - case op::Equiv: - case op::Implies: - SPOT_UNIMPLEMENTED(); - break; + // Inclusion-based rules + if (opt_.synt_impl | opt_.containment_checks) + { + trace << "bo: trying inclusion-based rules" << std::endl; + switch (o) + { + case op::Xor: + case op::Equiv: + case op::Implies: + SPOT_UNIMPLEMENTED(); + break; - case op::U: - // if a => b, then a U b = b - // if (a U b) => b, then a U b = b (for stronger containment) - if (c_->implication(a, b) - || (opt_.containment_checks_stronger - && c_->contained(bo, b))) - return b; - // if !a => b, then a U b = Fb - if (c_->implication_neg(a, b, false)) - return recurse(formula::F(b)); - // if a => b, then a U (b U c) = (b U c) - // if a => b, then a U (b W c) = (b W c) - if (b.is(op::U, op::W) && c_->implication(a, b[0])) - return b; - // if b => a, then a U (b U c) = (a U c) - if (b.is(op::U) && c_->implication(b[0], a)) - return recurse(formula::U(a, b[1])); - // if a => c, then a U (b R (c U d)) = (b R (c U d)) - // if a => c, then a U (b R (c W d)) = (b R (c W d)) - // if a => c, then a U (b M (c U d)) = (b M (c U d)) - // if a => c, then a U (b M (c W d)) = (b M (c W d)) - if (b.is(op::R, op::M)) - { - auto c1 = b[1]; - if (c1.is(op::U, op::W) && c_->implication(a, c1[0])) - return b; - } - // if a => b, then (a U c) U b = c U b - // if a => b, then (a W c) U b = c U b - if (a.is(op::U, op::W) && c_->implication(a[0], b)) - return recurse(formula::U(a[1], b)); - // if c => b, then (a U c) U b = (a U c) | b - if (a.is(op::U) && c_->implication(a[1], b)) - return recurse(formula::Or({a, b})); - break; + case op::U: + // if a => b, then a U b = b + // if (a U b) => b, then a U b = b (for stronger containment) + if (c_->implication(a, b) + || (opt_.containment_checks_stronger + && c_->contained(bo, b))) + return b; + // if !a => b, then a U b = Fb + if (c_->implication_neg(a, b, false)) + return recurse(formula::F(b)); + // if a => b, then a U (b U c) = (b U c) + // if a => b, then a U (b W c) = (b W c) + if (b.is(op::U, op::W) && c_->implication(a, b[0])) + return b; + // if b => a, then a U (b U c) = (a U c) + if (b.is(op::U) && c_->implication(b[0], a)) + return recurse(formula::U(a, b[1])); + // if a => c, then a U (b R (c U d)) = (b R (c U d)) + // if a => c, then a U (b R (c W d)) = (b R (c W d)) + // if a => c, then a U (b M (c U d)) = (b M (c U d)) + // if a => c, then a U (b M (c W d)) = (b M (c W d)) + if (b.is(op::R, op::M)) + { + auto c1 = b[1]; + if (c1.is(op::U, op::W) && c_->implication(a, c1[0])) + return b; + } + // if a => b, then (a U c) U b = c U b + // if a => b, then (a W c) U b = c U b + if (a.is(op::U, op::W) && c_->implication(a[0], b)) + return recurse(formula::U(a[1], b)); + // if c => b, then (a U c) U b = (a U c) | b + if (a.is(op::U) && c_->implication(a[1], b)) + return recurse(formula::Or({a, b})); + break; - case op::R: - // if b => a, then a R b = b - if (c_->implication(b, a)) - return b; - // if b => !a, then a R b = Gb - if (c_->implication_neg(b, a, true)) - return recurse(formula::G(b)); - // if b => a, then a R (b R c) = b R c - // if b => a, then a R (b M c) = b M c - if (b.is(op::R, op::M) && c_->implication(b[0], a)) - return b; - // if a => b, then a R (b R c) = a R c - if (b.is(op::R) && c_->implication(a, b[0])) - return recurse(formula::R(a, b[1])); - // if b => a, then (a R c) R b = c R b - // if b => a, then (a M c) R b = c R b - // if c => b, then (a R c) R b = (a & c) R b - // if c => b, then (a M c) R b = (a & c) R b - if (a.is(op::R, op::M)) - { - if (c_->implication(b, a[0])) - return recurse(formula::R(a[1], b)); - if (c_->implication(a[1], b)) - { - formula ac = formula::And({a[0], a[1]}); - return recurse(formula::R(ac, b)); - } - } - break; + case op::R: + // if b => a, then a R b = b + if (c_->implication(b, a)) + return b; + // if b => !a, then a R b = Gb + if (c_->implication_neg(b, a, true)) + return recurse(formula::G(b)); + // if b => a, then a R (b R c) = b R c + // if b => a, then a R (b M c) = b M c + if (b.is(op::R, op::M) && c_->implication(b[0], a)) + return b; + // if a => b, then a R (b R c) = a R c + if (b.is(op::R) && c_->implication(a, b[0])) + return recurse(formula::R(a, b[1])); + // if b => a, then (a R c) R b = c R b + // if b => a, then (a M c) R b = c R b + // if c => b, then (a R c) R b = (a & c) R b + // if c => b, then (a M c) R b = (a & c) R b + if (a.is(op::R, op::M)) + { + if (c_->implication(b, a[0])) + return recurse(formula::R(a[1], b)); + if (c_->implication(a[1], b)) + { + formula ac = formula::And({a[0], a[1]}); + return recurse(formula::R(ac, b)); + } + } + break; - case op::W: - // if a => b, then a W b = b - // if a W b => b, then a W b = b (for stronger containment) - if (c_->implication(a, b) - || (opt_.containment_checks_stronger - && c_->contained(bo, b))) - return b; - // if !a => b then a W b = 1 - if (c_->implication_neg(a, b, false)) - return formula::tt(); - // if a => b, then a W (b W c) = b W c - // (Beware: even if a => b we do not have a W (b U c) = b U c) - if (b.is(op::W) && c_->implication(a, b[0])) - return b; - // if b => a, then a W (b U c) = a W c - // if b => a, then a W (b W c) = a W c - if (b.is(op::U, op::W) && c_->implication(b[0], a)) - return recurse(formula::W(a, b[1])); - // if a => b, then (a U c) W b = c W b - // if a => b, then (a W c) W b = c W b - if (a.is(op::U, op::W) && c_->implication(a[0], b)) - return recurse(formula::W(a[1], b)); - // if c => b, then (a W c) W b = (a W c) | b - // if c => b, then (a U c) W b = (a U c) | b - if (a.is(op::U, op::W) && c_->implication(a[1], b)) - return recurse(formula::Or({a, b})); - break; + case op::W: + // if a => b, then a W b = b + // if a W b => b, then a W b = b (for stronger containment) + if (c_->implication(a, b) + || (opt_.containment_checks_stronger + && c_->contained(bo, b))) + return b; + // if !a => b then a W b = 1 + if (c_->implication_neg(a, b, false)) + return formula::tt(); + // if a => b, then a W (b W c) = b W c + // (Beware: even if a => b we do not have a W (b U c) = b U c) + if (b.is(op::W) && c_->implication(a, b[0])) + return b; + // if b => a, then a W (b U c) = a W c + // if b => a, then a W (b W c) = a W c + if (b.is(op::U, op::W) && c_->implication(b[0], a)) + return recurse(formula::W(a, b[1])); + // if a => b, then (a U c) W b = c W b + // if a => b, then (a W c) W b = c W b + if (a.is(op::U, op::W) && c_->implication(a[0], b)) + return recurse(formula::W(a[1], b)); + // if c => b, then (a W c) W b = (a W c) | b + // if c => b, then (a U c) W b = (a U c) | b + if (a.is(op::U, op::W) && c_->implication(a[1], b)) + return recurse(formula::Or({a, b})); + break; - case op::M: - // if b => a, then a M b = b - if (c_->implication(b, a)) - return b; - // if b => !a, then a M b = 0 - if (c_->implication_neg(b, a, true)) - return formula::ff(); - // if b => a, then a M (b M c) = b M c - if (b.is(op::M) && c_->implication(b[0], a)) - return b; - // if a => b, then a M (b M c) = a M c - // if a => b, then a M (b R c) = a M c - if (b.is(op::M, op::R) && c_->implication(a, b[0])) - return recurse(formula::M(a, b[1])); - // if b => a, then (a R c) M b = c M b - // if b => a, then (a M c) M b = c M b - if (a.is(op::R, op::M) && c_->implication(b, a[0])) - return recurse(formula::M(a[1], b)); - // if c => b, then (a M c) M b = (a & c) M b - if (a.is(op::M) && c_->implication(a[1], b)) - return - recurse(formula::M(formula::And({a[0], a[1]}), - b)); - break; + case op::M: + // if b => a, then a M b = b + if (c_->implication(b, a)) + return b; + // if b => !a, then a M b = 0 + if (c_->implication_neg(b, a, true)) + return formula::ff(); + // if b => a, then a M (b M c) = b M c + if (b.is(op::M) && c_->implication(b[0], a)) + return b; + // if a => b, then a M (b M c) = a M c + // if a => b, then a M (b R c) = a M c + if (b.is(op::M, op::R) && c_->implication(a, b[0])) + return recurse(formula::M(a, b[1])); + // if b => a, then (a R c) M b = c M b + // if b => a, then (a M c) M b = c M b + if (a.is(op::R, op::M) && c_->implication(b, a[0])) + return recurse(formula::M(a[1], b)); + // if c => b, then (a M c) M b = (a & c) M b + if (a.is(op::M) && c_->implication(a[1], b)) + return + recurse(formula::M(formula::And({a[0], a[1]}), + b)); + break; - default: - break; - } - trace << "bo: no inclusion-based rules matched" << std::endl; - } + default: + break; + } + trace << "bo: no inclusion-based rules matched" << std::endl; + } - if (!opt_.reduce_basics) - { - trace << "bo: basic reductions disabled" << std::endl; - return bo; - } + if (!opt_.reduce_basics) + { + trace << "bo: basic reductions disabled" << std::endl; + return bo; + } - trace << "bo: trying basic reductions" << std::endl; - // Rewrite U,R,W,M as F or G when possible. - // true U b == F(b) - if (bo.is(op::U) && a.is_tt()) - return recurse(formula::F(b)); - // false R b == G(b) - if (bo.is(op::R) && a.is_ff()) - return recurse(formula::G(b)); - // a W false == G(a) - if (bo.is(op::W) && b.is_ff()) - return recurse(formula::G(a)); - // a M true == F(a) - if (bo.is(op::M) && b.is_tt()) - return recurse(formula::F(a)); + trace << "bo: trying basic reductions" << std::endl; + // Rewrite U,R,W,M as F or G when possible. + // true U b == F(b) + if (bo.is(op::U) && a.is_tt()) + return recurse(formula::F(b)); + // false R b == G(b) + if (bo.is(op::R) && a.is_ff()) + return recurse(formula::G(b)); + // a W false == G(a) + if (bo.is(op::W) && b.is_ff()) + return recurse(formula::G(a)); + // a M true == F(a) + if (bo.is(op::M) && b.is_tt()) + return recurse(formula::F(a)); - if (bo.is(op::W, op::M) || bo.is(op::U, op::R)) - { - // X(a) U X(b) = X(a U b) - // X(a) R X(b) = X(a R b) - // X(a) W X(b) = X(a W b) - // X(a) M X(b) = X(a M b) - if (a.is(op::X) && b.is(op::X)) - return recurse(formula::X(formula::binop(o, - a[0], b[0]))); + if (bo.is(op::W, op::M) || bo.is(op::U, op::R)) + { + // X(a) U X(b) = X(a U b) + // X(a) R X(b) = X(a R b) + // X(a) W X(b) = X(a W b) + // X(a) M X(b) = X(a M b) + if (a.is(op::X) && b.is(op::X)) + return recurse(formula::X(formula::binop(o, + a[0], b[0]))); - if (bo.is(op::U, op::W)) - { - // a U Ga = Ga - // a W Ga = Ga - if (b.is(op::G) && a == b[0]) - return b; - // a U (b | c | G(a)) = a W (b | c) - // a W (b | c | G(a)) = a W (b | c) - if (b.is(op::Or)) - for (int i = 0, s = b.size(); i < s; ++i) - { - formula c = b[i]; - if (c.is(op::G) && c[0] == a) - return recurse(formula::W(a, b.all_but(i))); - } - // a U (b & a & c) == (b & c) M a - // a W (b & a & c) == (b & c) R a - if (b.is(op::And)) - for (int i = 0, s = b.size(); i < s; ++i) - if (b[i] == a) - return recurse(formula::binop(o == op::U ? - op::M : op::R, - b.all_but(i), a)); - // If b is Boolean: - // (Xc) U b = b | X(b M c) - // (Xc) W b = b | X(b R c) - if (!opt_.reduce_size_strictly - && a.is(op::X) && b.is_boolean()) - { - formula x = formula::X(formula::binop(o == op::U ? - op::M : op::R, - b, a[0])); - return recurse(formula::Or({b, x})); - } - } - else if (bo.is(op::M, op::R)) - { - // a R Fa = Fa - // a M Fa = Fa - if (b.is(op::F) && b[0] == a) - return b; + if (bo.is(op::U, op::W)) + { + // a U Ga = Ga + // a W Ga = Ga + if (b.is(op::G) && a == b[0]) + return b; + // a U (b | c | G(a)) = a W (b | c) + // a W (b | c | G(a)) = a W (b | c) + if (b.is(op::Or)) + for (int i = 0, s = b.size(); i < s; ++i) + { + formula c = b[i]; + if (c.is(op::G) && c[0] == a) + return recurse(formula::W(a, b.all_but(i))); + } + // a U (b & a & c) == (b & c) M a + // a W (b & a & c) == (b & c) R a + if (b.is(op::And)) + for (int i = 0, s = b.size(); i < s; ++i) + if (b[i] == a) + return recurse(formula::binop(o == op::U ? + op::M : op::R, + b.all_but(i), a)); + // If b is Boolean: + // (Xc) U b = b | X(b M c) + // (Xc) W b = b | X(b R c) + if (!opt_.reduce_size_strictly + && a.is(op::X) && b.is_boolean()) + { + formula x = formula::X(formula::binop(o == op::U ? + op::M : op::R, + b, a[0])); + return recurse(formula::Or({b, x})); + } + } + else if (bo.is(op::M, op::R)) + { + // a R Fa = Fa + // a M Fa = Fa + if (b.is(op::F) && b[0] == a) + return b; - // a R (b & c & F(a)) = a M (b & c) - // a M (b & c & F(a)) = a M (b & c) - if (b.is(op::And)) - for (int i = 0, s = b.size(); i < s; ++i) - { - formula c = b[i]; - if (c.is(op::F) && c[0] == a) - return recurse(formula::M(a, b.all_but(i))); - } - // a M (b | a | c) == (b | c) U a - // a R (b | a | c) == (b | c) W a - if (b.is(op::Or)) - for (int i = 0, s = b.size(); i < s; ++i) - if (b[i] == a) - return recurse(formula::binop(o == op::M ? - op::U : op::W, - b.all_but(i), a)); - // If b is Boolean: - // (Xc) R b = b & X(b W c) - // (Xc) M b = b & X(b U c) - if (!opt_.reduce_size_strictly - && a.is(op::X) && b.is_boolean()) - { - formula x = - formula::X(formula::binop(o == op::M ? op::U : op::W, - b, a[0])); - return recurse(formula::And({b, x})); - } - } - } - if (bo.is(op::UConcat) || bo.is(op::EConcat, op::EConcatMarked)) - return reduce_sere_ltl(bo); - return bo; + // a R (b & c & F(a)) = a M (b & c) + // a M (b & c & F(a)) = a M (b & c) + if (b.is(op::And)) + for (int i = 0, s = b.size(); i < s; ++i) + { + formula c = b[i]; + if (c.is(op::F) && c[0] == a) + return recurse(formula::M(a, b.all_but(i))); + } + // a M (b | a | c) == (b | c) U a + // a R (b | a | c) == (b | c) W a + if (b.is(op::Or)) + for (int i = 0, s = b.size(); i < s; ++i) + if (b[i] == a) + return recurse(formula::binop(o == op::M ? + op::U : op::W, + b.all_but(i), a)); + // If b is Boolean: + // (Xc) R b = b & X(b W c) + // (Xc) M b = b & X(b U c) + if (!opt_.reduce_size_strictly + && a.is(op::X) && b.is_boolean()) + { + formula x = + formula::X(formula::binop(o == op::M ? op::U : op::W, + b, a[0])); + return recurse(formula::And({b, x})); + } + } + } + if (bo.is(op::UConcat) || bo.is(op::EConcat, op::EConcatMarked)) + return reduce_sere_ltl(bo); + return bo; } formula - visit_multop(formula mo) + visit_multop(formula mo) { - auto recurse = [this](formula f) - { - return simplify_recursively(f, c_); - }; + auto recurse = [this](formula f) + { + return simplify_recursively(f, c_); + }; - unsigned mos = mo.size(); + unsigned mos = mo.size(); - if ((opt_.synt_impl | opt_.containment_checks) - && mo.is(op::Or, op::And)) - for (unsigned i = 0; i < mos; ++i) - { - formula fi = mo[i]; - formula fo = mo.all_but(i); - // if fi => fo, then fi | fo = fo - // if fo => fi, then fi & fo = fo - if ((mo.is(op::Or) && c_->implication(fi, fo)) - || (mo.is(op::And) && c_->implication(fo, fi))) - return recurse(fo); - // if fi => !fo, then fi & fo = false - // if fo => !fi, then fi & fo = false - // if !fi => fo, then fi | fo = true - // if !fo => fi, then fi | fo = true - bool is_and = mo.is(op::And); - if (c_->implication_neg(fi, fo, is_and) - || c_->implication_neg(fo, fi, is_and)) - return recurse(is_and ? formula::ff() : formula::tt()); - } + if ((opt_.synt_impl | opt_.containment_checks) + && mo.is(op::Or, op::And)) + for (unsigned i = 0; i < mos; ++i) + { + formula fi = mo[i]; + formula fo = mo.all_but(i); + // if fi => fo, then fi | fo = fo + // if fo => fi, then fi & fo = fo + if ((mo.is(op::Or) && c_->implication(fi, fo)) + || (mo.is(op::And) && c_->implication(fo, fi))) + return recurse(fo); + // if fi => !fo, then fi & fo = false + // if fo => !fi, then fi & fo = false + // if !fi => fo, then fi | fo = true + // if !fo => fi, then fi | fo = true + bool is_and = mo.is(op::And); + if (c_->implication_neg(fi, fo, is_and) + || c_->implication_neg(fo, fi, is_and)) + return recurse(is_and ? formula::ff() : formula::tt()); + } - vec res; - res.reserve(mos); - for (auto f: mo) - res.push_back(f); - op o = mo.kind(); + vec res; + res.reserve(mos); + for (auto f: mo) + res.push_back(f); + op o = mo.kind(); - // basics reduction do not concern Boolean formulas, - // so don't waste time trying to apply them. - if (opt_.reduce_basics && !mo.is_boolean()) - { - switch (o) - { - case op::And: - assert(!mo.is_sere_formula()); - { - // a & X(G(a&b...) & c...) = Ga & X(G(b...) & c...) - // a & (Xa W b) = b R a - // a & (Xa U b) = b M a - // a & (b | X(b R a)) = b R a - // a & (b | X(b M a)) = b M a - if (!mo.is_syntactic_stutter_invariant()) // Skip if no X. - { - typedef std::unordered_set fset_t; - typedef std::unordered_map> fmap_t; - fset_t xgset; // XG(...) - fset_t xset; // X(...) - fmap_t wuset; // (X...)W(...) or (X...)U(...) + // basics reduction do not concern Boolean formulas, + // so don't waste time trying to apply them. + if (opt_.reduce_basics && !mo.is_boolean()) + { + switch (o) + { + case op::And: + assert(!mo.is_sere_formula()); + { + // a & X(G(a&b...) & c...) = Ga & X(G(b...) & c...) + // a & (Xa W b) = b R a + // a & (Xa U b) = b M a + // a & (b | X(b R a)) = b R a + // a & (b | X(b M a)) = b M a + if (!mo.is_syntactic_stutter_invariant()) // Skip if no X. + { + typedef std::unordered_set fset_t; + typedef std::unordered_map> fmap_t; + fset_t xgset; // XG(...) + fset_t xset; // X(...) + fmap_t wuset; // (X...)W(...) or (X...)U(...) - std::vector tokill(mos); + std::vector tokill(mos); - // Make a pass to search for subterms - // of the form XGa or X(... & G(...&a&...) & ...) - for (unsigned n = 0; n < mos; ++n) - { - if (!res[n]) - continue; - if (res[n].is_syntactic_stutter_invariant()) - continue; + // Make a pass to search for subterms + // of the form XGa or X(... & G(...&a&...) & ...) + for (unsigned n = 0; n < mos; ++n) + { + if (!res[n]) + continue; + if (res[n].is_syntactic_stutter_invariant()) + continue; - if (formula xarg = is_XWU(res[n])) - { - wuset[xarg].insert(n); - continue; - } + if (formula xarg = is_XWU(res[n])) + { + wuset[xarg].insert(n); + continue; + } - // Now we are looking for - // - X(...) - // - b | X(b R ...) - // - b | X(b M ...) - if (formula barg = is_bXbRM(res[n])) - { - wuset[barg[1]].insert(n); - continue; - } + // Now we are looking for + // - X(...) + // - b | X(b R ...) + // - b | X(b M ...) + if (formula barg = is_bXbRM(res[n])) + { + wuset[barg[1]].insert(n); + continue; + } - if (!res[n].is(op::X)) - continue; + if (!res[n].is(op::X)) + continue; - formula c = res[n][0]; - auto handle_G = [&xgset](formula c) - { - formula a2 = c[0]; - if (a2.is(op::And)) - for (auto c: a2) - xgset.insert(c); - else - xgset.insert(a2); - }; + formula c = res[n][0]; + auto handle_G = [&xgset](formula c) + { + formula a2 = c[0]; + if (a2.is(op::And)) + for (auto c: a2) + xgset.insert(c); + else + xgset.insert(a2); + }; - if (c.is(op::G)) - { - handle_G(c); - } - else if (c.is(op::And)) - { - for (auto cc: c) - if (cc.is(op::G)) - handle_G(cc); - else - xset.insert(cc); - } - else - { - xset.insert(c); - } - res[n] = nullptr; - } - // Make a second pass to check if the "a" - // terms can be used to simplify "Xa W b", - // "Xa U b", "b | X(b R a)", or "b | X(b M a)". - vec resorig(res); - for (unsigned n = 0; n < mos; ++n) - { - formula x = resorig[n]; - if (!x) - continue; - fmap_t::const_iterator gs = wuset.find(x); - if (gs == wuset.end()) - continue; + if (c.is(op::G)) + { + handle_G(c); + } + else if (c.is(op::And)) + { + for (auto cc: c) + if (cc.is(op::G)) + handle_G(cc); + else + xset.insert(cc); + } + else + { + xset.insert(c); + } + res[n] = nullptr; + } + // Make a second pass to check if the "a" + // terms can be used to simplify "Xa W b", + // "Xa U b", "b | X(b R a)", or "b | X(b M a)". + vec resorig(res); + for (unsigned n = 0; n < mos; ++n) + { + formula x = resorig[n]; + if (!x) + continue; + fmap_t::const_iterator gs = wuset.find(x); + if (gs == wuset.end()) + continue; - for (unsigned pos: gs->second) - { - formula wu = resorig[pos]; - if (wu.is(op::W, op::U)) - { - // a & (Xa W b) = b R a - // a & (Xa U b) = b M a - op t = wu.is(op::U) ? op::M : op::R; - assert(wu[0].is(op::X)); - formula a = wu[0][0]; - formula b = wu[1]; - res[pos] = formula::binop(t, b, a); - } - else - { - // a & (b | X(b R a)) = b R a - // a & (b | X(b M a)) = b M a - wu = is_bXbRM(resorig[pos]); - assert(wu); - res[pos] = wu; - } - // Remember to kill "a". - tokill[n] = true; - } - } + for (unsigned pos: gs->second) + { + formula wu = resorig[pos]; + if (wu.is(op::W, op::U)) + { + // a & (Xa W b) = b R a + // a & (Xa U b) = b M a + op t = wu.is(op::U) ? op::M : op::R; + assert(wu[0].is(op::X)); + formula a = wu[0][0]; + formula b = wu[1]; + res[pos] = formula::binop(t, b, a); + } + else + { + // a & (b | X(b R a)) = b R a + // a & (b | X(b M a)) = b M a + wu = is_bXbRM(resorig[pos]); + assert(wu); + res[pos] = wu; + } + // Remember to kill "a". + tokill[n] = true; + } + } - // Make third pass to search for terms 'a' - // that also appears as 'XGa'. Replace them - // by 'Ga' and delete XGa. - for (unsigned n = 0; n < mos; ++n) - { - formula x = res[n]; - if (!x) - continue; - fset_t::const_iterator g = xgset.find(x); - if (g != xgset.end()) - { - // x can appear only once. - formula gf = *g; - xgset.erase(g); - res[n] = formula::G(x); - } - else if (tokill[n]) - { - res[n] = nullptr; - } - } + // Make third pass to search for terms 'a' + // that also appears as 'XGa'. Replace them + // by 'Ga' and delete XGa. + for (unsigned n = 0; n < mos; ++n) + { + formula x = res[n]; + if (!x) + continue; + fset_t::const_iterator g = xgset.find(x); + if (g != xgset.end()) + { + // x can appear only once. + formula gf = *g; + xgset.erase(g); + res[n] = formula::G(x); + } + else if (tokill[n]) + { + res[n] = nullptr; + } + } - vec xv; - unsigned xgs = xgset.size(); - xv.reserve(xset.size() + 1); - if (xgs > 0) - { - vec xgv; - xgv.reserve(xgs); - for (auto f: xgset) - xgv.push_back(f); - xv.emplace_back(unop_multop(op::G, op::And, xgv)); - } - for (auto f: xset) - xv.emplace_back(f); - res.push_back(unop_multop(op::X, op::And, xv)); - } + vec xv; + unsigned xgs = xgset.size(); + xv.reserve(xset.size() + 1); + if (xgs > 0) + { + vec xgv; + xgv.reserve(xgs); + for (auto f: xgset) + xgv.push_back(f); + xv.emplace_back(unop_multop(op::G, op::And, xgv)); + } + for (auto f: xset) + xv.emplace_back(f); + res.push_back(unop_multop(op::X, op::And, xv)); + } - // Gather all operands by type. - mospliter s(mospliter::Strip_X | - mospliter::Strip_FG | - mospliter::Strip_G | - mospliter::Split_F | - mospliter::Split_U_or_W | - mospliter::Split_R_or_M | - mospliter::Split_EventUniv, - res, c_); + // Gather all operands by type. + mospliter s(mospliter::Strip_X | + mospliter::Strip_FG | + mospliter::Strip_G | + mospliter::Split_F | + mospliter::Split_U_or_W | + mospliter::Split_R_or_M | + mospliter::Split_EventUniv, + res, c_); - // FG(a) & FG(b) = FG(a & b) - formula allFG = unop_unop_multop(op::F, op::G, op::And, - std::move(*s.res_FG)); - // Xa & Xb = X(a & b) - // Xa & Xb & FG(c) = X(a & b & FG(c)) - // For Universal&Eventual formulae f1...fn we also have: - // Xa & Xb & f1...fn = X(a & b & f1...fn) - if (!s.res_X->empty() && !opt_.favor_event_univ) - { - s.res_X->push_back(allFG); - allFG = nullptr; - s.res_X->insert(s.res_X->begin(), - s.res_EventUniv->begin(), - s.res_EventUniv->end()); - } - else - // If f1...fn are event&univ formulae, with at least - // one formula of the form G(...), - // Rewrite g & f1...fn as g & G(f1..fn) while - // stripping any leading G from f1...fn. - // This gathers eventual&universal formulae - // under the same term. - { - vec eu; - bool seen_g = false; - for (auto f: *s.res_EventUniv) - { - if (f.is_eventual() && f.is_universal()) - { - if (f.is(op::G)) - { - seen_g = true; - eu.push_back(f[0]); - } - else - { - eu.push_back(f); - } - } - else - { - s.res_other->push_back(f); - } - } - if (seen_g) - { - eu.push_back(allFG); - allFG = nullptr; - s.res_other->push_back(unop_multop(op::G, op::And, - eu)); - } - else - { - s.res_other->insert(s.res_other->end(), - eu.begin(), eu.end()); - } - } + // FG(a) & FG(b) = FG(a & b) + formula allFG = unop_unop_multop(op::F, op::G, op::And, + std::move(*s.res_FG)); + // Xa & Xb = X(a & b) + // Xa & Xb & FG(c) = X(a & b & FG(c)) + // For Universal&Eventual formulae f1...fn we also have: + // Xa & Xb & f1...fn = X(a & b & f1...fn) + if (!s.res_X->empty() && !opt_.favor_event_univ) + { + s.res_X->push_back(allFG); + allFG = nullptr; + s.res_X->insert(s.res_X->begin(), + s.res_EventUniv->begin(), + s.res_EventUniv->end()); + } + else + // If f1...fn are event&univ formulae, with at least + // one formula of the form G(...), + // Rewrite g & f1...fn as g & G(f1..fn) while + // stripping any leading G from f1...fn. + // This gathers eventual&universal formulae + // under the same term. + { + vec eu; + bool seen_g = false; + for (auto f: *s.res_EventUniv) + { + if (f.is_eventual() && f.is_universal()) + { + if (f.is(op::G)) + { + seen_g = true; + eu.push_back(f[0]); + } + else + { + eu.push_back(f); + } + } + else + { + s.res_other->push_back(f); + } + } + if (seen_g) + { + eu.push_back(allFG); + allFG = nullptr; + s.res_other->push_back(unop_multop(op::G, op::And, + eu)); + } + else + { + s.res_other->insert(s.res_other->end(), + eu.begin(), eu.end()); + } + } - // Xa & Xb & f1...fn = X(a & b & f1...fn) - // is built at the end of this op::And case. - // G(a) & G(b) = G(a & b) - // is built at the end of this op::And case. + // Xa & Xb & f1...fn = X(a & b & f1...fn) + // is built at the end of this op::And case. + // G(a) & G(b) = G(a & b) + // is built at the end of this op::And case. - // The following three loops perform these rewritings: - // (a U b) & (c U b) = (a & c) U b - // (a U b) & (c W b) = (a & c) U b - // (a W b) & (c W b) = (a & c) W b - // (a R b) & (a R c) = a R (b & c) - // (a R b) & (a M c) = a M (b & c) - // (a M b) & (a M c) = a M (b & c) - // F(a) & (a R b) = a M b - // F(a) & (a M b) = a M b - // F(b) & (a W b) = a U b - // F(b) & (a U b) = a U b - typedef std::unordered_map fmap_t; - fmap_t uwmap; // associates "b" to "a U b" or "a W b" - fmap_t rmmap; // associates "a" to "a R b" or "a M b" - // (a U b) & (c U b) = (a & c) U b - // (a U b) & (c W b) = (a & c) U b - // (a W b) & (c W b) = (a & c) W b - for (auto i = s.res_U_or_W->begin(); - i != s.res_U_or_W->end(); ++i) - { - formula b = (*i)[1]; - auto j = uwmap.find(b); - if (j == uwmap.end()) - { - // First occurrence. - uwmap[b] = i; - continue; - } - // We already have one occurrence. Merge them. - formula old = *j->second; - op o = op::W; - if (i->is(op::U) || old.is(op::U)) - o = op::U; - formula fst_arg = formula::And({old[0], (*i)[0]}); - *j->second = formula::binop(o, fst_arg, b); - assert(j->second->is(o)); - *i = nullptr; - } - // (a R b) & (a R c) = a R (b & c) - // (a R b) & (a M c) = a M (b & c) - // (a M b) & (a M c) = a M (b & c) - for (auto i = s.res_R_or_M->begin(); - i != s.res_R_or_M->end(); ++i) - { - formula a = (*i)[0]; - auto j = rmmap.find(a); - if (j == rmmap.end()) - { - // First occurrence. - rmmap[a] = i; - continue; - } - // We already have one occurrence. Merge them. - formula old = *j->second; - op o = op::R; - if (i->is(op::M) || old.is(op::M)) - o = op::M; - formula snd_arg = formula::And({old[1], (*i)[1]}); - *j->second = formula::binop(o, a, snd_arg); - assert(j->second->is(o)); - *i = nullptr; - } - // F(b) & (a W b) = a U b - // F(b) & (a U b) = a U b - // F(a) & (a R b) = a M b - // F(a) & (a M b) = a M b - for (auto& f: *s.res_F) - { - bool superfluous = false; - formula c = f[0]; + // The following three loops perform these rewritings: + // (a U b) & (c U b) = (a & c) U b + // (a U b) & (c W b) = (a & c) U b + // (a W b) & (c W b) = (a & c) W b + // (a R b) & (a R c) = a R (b & c) + // (a R b) & (a M c) = a M (b & c) + // (a M b) & (a M c) = a M (b & c) + // F(a) & (a R b) = a M b + // F(a) & (a M b) = a M b + // F(b) & (a W b) = a U b + // F(b) & (a U b) = a U b + typedef std::unordered_map fmap_t; + fmap_t uwmap; // associates "b" to "a U b" or "a W b" + fmap_t rmmap; // associates "a" to "a R b" or "a M b" + // (a U b) & (c U b) = (a & c) U b + // (a U b) & (c W b) = (a & c) U b + // (a W b) & (c W b) = (a & c) W b + for (auto i = s.res_U_or_W->begin(); + i != s.res_U_or_W->end(); ++i) + { + formula b = (*i)[1]; + auto j = uwmap.find(b); + if (j == uwmap.end()) + { + // First occurrence. + uwmap[b] = i; + continue; + } + // We already have one occurrence. Merge them. + formula old = *j->second; + op o = op::W; + if (i->is(op::U) || old.is(op::U)) + o = op::U; + formula fst_arg = formula::And({old[0], (*i)[0]}); + *j->second = formula::binop(o, fst_arg, b); + assert(j->second->is(o)); + *i = nullptr; + } + // (a R b) & (a R c) = a R (b & c) + // (a R b) & (a M c) = a M (b & c) + // (a M b) & (a M c) = a M (b & c) + for (auto i = s.res_R_or_M->begin(); + i != s.res_R_or_M->end(); ++i) + { + formula a = (*i)[0]; + auto j = rmmap.find(a); + if (j == rmmap.end()) + { + // First occurrence. + rmmap[a] = i; + continue; + } + // We already have one occurrence. Merge them. + formula old = *j->second; + op o = op::R; + if (i->is(op::M) || old.is(op::M)) + o = op::M; + formula snd_arg = formula::And({old[1], (*i)[1]}); + *j->second = formula::binop(o, a, snd_arg); + assert(j->second->is(o)); + *i = nullptr; + } + // F(b) & (a W b) = a U b + // F(b) & (a U b) = a U b + // F(a) & (a R b) = a M b + // F(a) & (a M b) = a M b + for (auto& f: *s.res_F) + { + bool superfluous = false; + formula c = f[0]; - fmap_t::iterator j = uwmap.find(c); - if (j != uwmap.end()) - { - superfluous = true; - formula bo = *j->second; - if (bo.is(op::W)) - { - *j->second = formula::U(bo[0], bo[1]); - assert(j->second->is(op::U)); - } - } - j = rmmap.find(c); - if (j != rmmap.end()) - { - superfluous = true; - formula bo = *j->second; - if (bo.is(op::R)) - { - *j->second = formula::M(bo[0], bo[1]); - assert(j->second->is(op::M)); - } - } - if (superfluous) - f = nullptr; - } + fmap_t::iterator j = uwmap.find(c); + if (j != uwmap.end()) + { + superfluous = true; + formula bo = *j->second; + if (bo.is(op::W)) + { + *j->second = formula::U(bo[0], bo[1]); + assert(j->second->is(op::U)); + } + } + j = rmmap.find(c); + if (j != rmmap.end()) + { + superfluous = true; + formula bo = *j->second; + if (bo.is(op::R)) + { + *j->second = formula::M(bo[0], bo[1]); + assert(j->second->is(op::M)); + } + } + if (superfluous) + f = nullptr; + } - s.res_other->reserve(s.res_other->size() - + s.res_F->size() - + s.res_U_or_W->size() - + s.res_R_or_M->size() - + 3); - s.res_other->insert(s.res_other->end(), - s.res_F->begin(), - s.res_F->end()); - s.res_other->insert(s.res_other->end(), - s.res_U_or_W->begin(), - s.res_U_or_W->end()); - s.res_other->insert(s.res_other->end(), - s.res_R_or_M->begin(), - s.res_R_or_M->end()); + s.res_other->reserve(s.res_other->size() + + s.res_F->size() + + s.res_U_or_W->size() + + s.res_R_or_M->size() + + 3); + s.res_other->insert(s.res_other->end(), + s.res_F->begin(), + s.res_F->end()); + s.res_other->insert(s.res_other->end(), + s.res_U_or_W->begin(), + s.res_U_or_W->end()); + s.res_other->insert(s.res_other->end(), + s.res_R_or_M->begin(), + s.res_R_or_M->end()); - // Those "G" formulae that are eventual can be - // postponed inside the X term if there is one. - // - // In effect we rewrite - // Xa&Xb&GFc&GFd&Ge as X(a&b&G(Fc&Fd))&Ge - if (!s.res_X->empty() && !opt_.favor_event_univ) - { - vec event; - for (auto& f: *s.res_G) - if (f.is_eventual()) - { - event.push_back(f); - f = nullptr; // Remove it from res_G. - } - s.res_X->push_back(unop_multop(op::G, op::And, - std::move(event))); - } + // Those "G" formulae that are eventual can be + // postponed inside the X term if there is one. + // + // In effect we rewrite + // Xa&Xb&GFc&GFd&Ge as X(a&b&G(Fc&Fd))&Ge + if (!s.res_X->empty() && !opt_.favor_event_univ) + { + vec event; + for (auto& f: *s.res_G) + if (f.is_eventual()) + { + event.push_back(f); + f = nullptr; // Remove it from res_G. + } + s.res_X->push_back(unop_multop(op::G, op::And, + std::move(event))); + } - // G(a) & G(b) & ... = G(a & b & ...) - formula allG = unop_multop(op::G, op::And, - std::move(*s.res_G)); - // Xa & Xb & ... = X(a & b & ...) - formula allX = unop_multop(op::X, op::And, - std::move(*s.res_X)); - s.res_other->push_back(allX); - s.res_other->push_back(allG); - s.res_other->push_back(allFG); - formula r = formula::And(std::move(*s.res_other)); - // If we altered the formula in some way, process - // it another time. - if (r != mo) - return recurse(r); - return r; - } - case op::AndRat: - { - mospliter s(mospliter::Split_Bool, res, c_); - if (!s.res_Bool->empty()) - { - // b1 & b2 & b3 = b1 ∧ b2 ∧ b3 - formula b = formula::And(std::move(*s.res_Bool)); + // G(a) & G(b) & ... = G(a & b & ...) + formula allG = unop_multop(op::G, op::And, + std::move(*s.res_G)); + // Xa & Xb & ... = X(a & b & ...) + formula allX = unop_multop(op::X, op::And, + std::move(*s.res_X)); + s.res_other->push_back(allX); + s.res_other->push_back(allG); + s.res_other->push_back(allFG); + formula r = formula::And(std::move(*s.res_other)); + // If we altered the formula in some way, process + // it another time. + if (r != mo) + return recurse(r); + return r; + } + case op::AndRat: + { + mospliter s(mospliter::Split_Bool, res, c_); + if (!s.res_Bool->empty()) + { + // b1 & b2 & b3 = b1 ∧ b2 ∧ b3 + formula b = formula::And(std::move(*s.res_Bool)); - vec ares; - for (auto& f: *s.res_other) - switch (f.kind()) - { - case op::Star: - // b && r[*i..j] = b & r if i<=1<=j - // = 0 otherwise - if (f.min() > 1 || f.max() < 1) - return formula::ff(); - ares.push_back(f[0]); - f = nullptr; - break; - case op::Fusion: - // b && {r1:..:rn} = b && r1 && .. && rn - for (auto ri: f) - ares.push_back(ri); - f = nullptr; - break; - case op::Concat: - // b && {r1;...;rn} = - // - b && ri if there is only one ri - // that does not accept [*0] - // - b && (r1|...|rn) if all ri - // do not accept [*0] - // - 0 if more than one ri accept [*0] - { - formula ri = nullptr; - unsigned nonempty = 0; - unsigned rs = f.size(); - for (unsigned j = 0; j < rs; ++j) - { - formula jf = f[j]; - if (!jf.accepts_eword()) - { - ri = jf; - ++nonempty; - } - } - if (nonempty == 1) - { - ares.push_back(ri); - } - else if (nonempty == 0) - { - vec sum; - for (auto j: f) - sum.push_back(j); - ares.emplace_back(formula::OrRat(sum)); - } - else - { - return formula::ff(); - } - f = nullptr; - break; - } - default: - ares.push_back(f); - f = nullptr; - break; - } - ares.push_back(b); - auto r = formula::AndRat(std::move(ares)); - // If we altered the formula in some way, process - // it another time. - if (r != mo) - return recurse(r); - return r; - } - // No Boolean as argument of &&. + vec ares; + for (auto& f: *s.res_other) + switch (f.kind()) + { + case op::Star: + // b && r[*i..j] = b & r if i<=1<=j + // = 0 otherwise + if (f.min() > 1 || f.max() < 1) + return formula::ff(); + ares.push_back(f[0]); + f = nullptr; + break; + case op::Fusion: + // b && {r1:..:rn} = b && r1 && .. && rn + for (auto ri: f) + ares.push_back(ri); + f = nullptr; + break; + case op::Concat: + // b && {r1;...;rn} = + // - b && ri if there is only one ri + // that does not accept [*0] + // - b && (r1|...|rn) if all ri + // do not accept [*0] + // - 0 if more than one ri accept [*0] + { + formula ri = nullptr; + unsigned nonempty = 0; + unsigned rs = f.size(); + for (unsigned j = 0; j < rs; ++j) + { + formula jf = f[j]; + if (!jf.accepts_eword()) + { + ri = jf; + ++nonempty; + } + } + if (nonempty == 1) + { + ares.push_back(ri); + } + else if (nonempty == 0) + { + vec sum; + for (auto j: f) + sum.push_back(j); + ares.emplace_back(formula::OrRat(sum)); + } + else + { + return formula::ff(); + } + f = nullptr; + break; + } + default: + ares.push_back(f); + f = nullptr; + break; + } + ares.push_back(b); + auto r = formula::AndRat(std::move(ares)); + // If we altered the formula in some way, process + // it another time. + if (r != mo) + return recurse(r); + return r; + } + // No Boolean as argument of &&. - // Look for occurrences of {b;r} or {b:r}. We have - // {b1;r1}&&{b2;r2} = {b1&&b2};{r1&&r2} - // head1 tail1 - // {b1:r1}&&{b2:r2} = {b1&&b2}:{r1&&r2} - // head2 tail2 - vec head1; - vec tail1; - vec head2; - vec tail2; - for (auto& i: *s.res_other) - { - if (!i) - continue; - if (!i.is(op::Concat, op::Fusion)) - continue; - formula h = i[0]; - if (!h.is_boolean()) - continue; - if (i.is(op::Concat)) - { - head1.push_back(h); - tail1.push_back(i.all_but(0)); - } - else // op::Fusion - { - head2.push_back(h); - tail2.push_back(i.all_but(0)); - } - i = nullptr; - } - if (!head1.empty()) - { - formula h = formula::And(std::move(head1)); - formula t = formula::AndRat(std::move(tail1)); - s.res_other->push_back(formula::Concat({h, t})); - } - if (!head2.empty()) - { - formula h = formula::And(std::move(head2)); - formula t = formula::AndRat(std::move(tail2)); - s.res_other->push_back(formula::Fusion({h, t})); - } + // Look for occurrences of {b;r} or {b:r}. We have + // {b1;r1}&&{b2;r2} = {b1&&b2};{r1&&r2} + // head1 tail1 + // {b1:r1}&&{b2:r2} = {b1&&b2}:{r1&&r2} + // head2 tail2 + vec head1; + vec tail1; + vec head2; + vec tail2; + for (auto& i: *s.res_other) + { + if (!i) + continue; + if (!i.is(op::Concat, op::Fusion)) + continue; + formula h = i[0]; + if (!h.is_boolean()) + continue; + if (i.is(op::Concat)) + { + head1.push_back(h); + tail1.push_back(i.all_but(0)); + } + else // op::Fusion + { + head2.push_back(h); + tail2.push_back(i.all_but(0)); + } + i = nullptr; + } + if (!head1.empty()) + { + formula h = formula::And(std::move(head1)); + formula t = formula::AndRat(std::move(tail1)); + s.res_other->push_back(formula::Concat({h, t})); + } + if (!head2.empty()) + { + formula h = formula::And(std::move(head2)); + formula t = formula::AndRat(std::move(tail2)); + s.res_other->push_back(formula::Fusion({h, t})); + } - // {r1;b1}&&{r2;b2} = {r1&&r2};{b1∧b2} - // head3 tail3 - // {r1:b1}&&{r2:b2} = {r1&&r2}:{b1∧b2} - // head4 tail4 - vec head3; - vec tail3; - vec head4; - vec tail4; - for (auto& i: *s.res_other) - { - if (!i) - continue; - if (!i.is(op::Concat, op::Fusion)) - continue; - unsigned s = i.size() - 1; - formula t = i[s]; - if (!t.is_boolean()) - continue; - if (i.is(op::Concat)) - { - tail3.push_back(t); - head3.push_back(i.all_but(s)); - } - else // op::Fusion - { - tail4.push_back(t); - head4.push_back(i.all_but(s)); - } - i = nullptr; - } - if (!head3.empty()) - { - formula h = formula::AndRat(std::move(head3)); - formula t = formula::And(std::move(tail3)); - s.res_other->push_back(formula::Concat({h, t})); - } - if (!head4.empty()) - { - formula h = formula::AndRat(std::move(head4)); - formula t = formula::And(std::move(tail4)); - s.res_other->push_back(formula::Fusion({h, t})); - } + // {r1;b1}&&{r2;b2} = {r1&&r2};{b1∧b2} + // head3 tail3 + // {r1:b1}&&{r2:b2} = {r1&&r2}:{b1∧b2} + // head4 tail4 + vec head3; + vec tail3; + vec head4; + vec tail4; + for (auto& i: *s.res_other) + { + if (!i) + continue; + if (!i.is(op::Concat, op::Fusion)) + continue; + unsigned s = i.size() - 1; + formula t = i[s]; + if (!t.is_boolean()) + continue; + if (i.is(op::Concat)) + { + tail3.push_back(t); + head3.push_back(i.all_but(s)); + } + else // op::Fusion + { + tail4.push_back(t); + head4.push_back(i.all_but(s)); + } + i = nullptr; + } + if (!head3.empty()) + { + formula h = formula::AndRat(std::move(head3)); + formula t = formula::And(std::move(tail3)); + s.res_other->push_back(formula::Concat({h, t})); + } + if (!head4.empty()) + { + formula h = formula::AndRat(std::move(head4)); + formula t = formula::And(std::move(tail4)); + s.res_other->push_back(formula::Fusion({h, t})); + } - auto r = formula::AndRat(std::move(*s.res_other)); - // If we altered the formula in some way, process - // it another time. - if (r != mo) - return recurse(r); - return r; - } - case op::Or: - { - // a | X(F(a) | c...) = Fa | X(c...) - // a | (Xa R b) = b W a - // a | (Xa M b) = b U a - // a | (b & X(b W a)) = b W a - // a | (b & X(b U a)) = b U a - if (!mo.is_syntactic_stutter_invariant()) // Skip if no X - { - typedef std::unordered_set fset_t; - typedef std::unordered_map> fmap_t; - fset_t xfset; // XF(...) - fset_t xset; // X(...) - fmap_t rmset; // (X...)R(...) or (X...)M(...) or - // b & X(b W ...) or b & X(b U ...) + auto r = formula::AndRat(std::move(*s.res_other)); + // If we altered the formula in some way, process + // it another time. + if (r != mo) + return recurse(r); + return r; + } + case op::Or: + { + // a | X(F(a) | c...) = Fa | X(c...) + // a | (Xa R b) = b W a + // a | (Xa M b) = b U a + // a | (b & X(b W a)) = b W a + // a | (b & X(b U a)) = b U a + if (!mo.is_syntactic_stutter_invariant()) // Skip if no X + { + typedef std::unordered_set fset_t; + typedef std::unordered_map> fmap_t; + fset_t xfset; // XF(...) + fset_t xset; // X(...) + fmap_t rmset; // (X...)R(...) or (X...)M(...) or + // b & X(b W ...) or b & X(b U ...) - std::vector tokill(mos); + std::vector tokill(mos); - // Make a pass to search for subterms - // of the form XFa or X(... | F(...|a|...) | ...) - for (unsigned n = 0; n < mos; ++n) - { - if (!res[n]) - continue; - if (res[n].is_syntactic_stutter_invariant()) - continue; + // Make a pass to search for subterms + // of the form XFa or X(... | F(...|a|...) | ...) + for (unsigned n = 0; n < mos; ++n) + { + if (!res[n]) + continue; + if (res[n].is_syntactic_stutter_invariant()) + continue; - if (formula xarg = is_XRM(res[n])) - { - rmset[xarg].insert(n); - continue; - } + if (formula xarg = is_XRM(res[n])) + { + rmset[xarg].insert(n); + continue; + } - // Now we are looking for - // - X(...) - // - b & X(b W ...) - // - b & X(b U ...) - if (formula barg = is_bXbWU(res[n])) - { - rmset[barg[1]].insert(n); - continue; - } + // Now we are looking for + // - X(...) + // - b & X(b W ...) + // - b & X(b U ...) + if (formula barg = is_bXbWU(res[n])) + { + rmset[barg[1]].insert(n); + continue; + } - if (!res[n].is(op::X)) - continue; + if (!res[n].is(op::X)) + continue; - formula c = res[n][0]; + formula c = res[n][0]; - auto handle_F = [&xfset](formula c) - { - formula a2 = c[0]; - if (a2.is(op::Or)) - for (auto c: a2) - xfset.insert(c); - else - xfset.insert(a2); - }; + auto handle_F = [&xfset](formula c) + { + formula a2 = c[0]; + if (a2.is(op::Or)) + for (auto c: a2) + xfset.insert(c); + else + xfset.insert(a2); + }; - if (c.is(op::F)) - { - handle_F(c); - } - else if (c.is(op::Or)) - { - for (auto cc: c) - if (cc.is(op::F)) - handle_F(cc); - else - xset.insert(cc); - } - else - { - xset.insert(c); - } - res[n] = nullptr; - } - // Make a second pass to check if we can - // remove all instance of XF(a). - unsigned allofthem = xfset.size(); - vec resorig(res); - for (unsigned n = 0; n < mos; ++n) - { - formula x = resorig[n]; - if (!x) - continue; - fset_t::const_iterator f = xfset.find(x); - if (f != xfset.end()) - --allofthem; - assert(allofthem != -1U); - // At the same time, check if "a" can also - // be used to simplify "Xa R b", "Xa M b". - // "b & X(b W a)", or "b & X(b U a)". - fmap_t::const_iterator gs = rmset.find(x); - if (gs == rmset.end()) - continue; - for (unsigned pos: gs->second) - { - formula rm = resorig[pos]; - if (rm.is(op::M, op::R)) - { - // a | (Xa R b) = b W a - // a | (Xa M b) = b U a - op t = rm.is(op::M) ? op::U : op::W; - assert(rm[0].is(op::X)); - formula a = rm[0][0]; - formula b = rm[1]; - res[pos] = formula::binop(t, b, a); - } - else - { - // a | (b & X(b W a)) = b W a - // a | (b & X(b U a)) = b U a - rm = is_bXbWU(resorig[pos]); - assert(rm); - res[pos] = rm; - } - // Remember to kill "a". - tokill[n] = true; - } - } + if (c.is(op::F)) + { + handle_F(c); + } + else if (c.is(op::Or)) + { + for (auto cc: c) + if (cc.is(op::F)) + handle_F(cc); + else + xset.insert(cc); + } + else + { + xset.insert(c); + } + res[n] = nullptr; + } + // Make a second pass to check if we can + // remove all instance of XF(a). + unsigned allofthem = xfset.size(); + vec resorig(res); + for (unsigned n = 0; n < mos; ++n) + { + formula x = resorig[n]; + if (!x) + continue; + fset_t::const_iterator f = xfset.find(x); + if (f != xfset.end()) + --allofthem; + assert(allofthem != -1U); + // At the same time, check if "a" can also + // be used to simplify "Xa R b", "Xa M b". + // "b & X(b W a)", or "b & X(b U a)". + fmap_t::const_iterator gs = rmset.find(x); + if (gs == rmset.end()) + continue; + for (unsigned pos: gs->second) + { + formula rm = resorig[pos]; + if (rm.is(op::M, op::R)) + { + // a | (Xa R b) = b W a + // a | (Xa M b) = b U a + op t = rm.is(op::M) ? op::U : op::W; + assert(rm[0].is(op::X)); + formula a = rm[0][0]; + formula b = rm[1]; + res[pos] = formula::binop(t, b, a); + } + else + { + // a | (b & X(b W a)) = b W a + // a | (b & X(b U a)) = b U a + rm = is_bXbWU(resorig[pos]); + assert(rm); + res[pos] = rm; + } + // Remember to kill "a". + tokill[n] = true; + } + } - // If we can remove all of them... - if (allofthem == 0) - // Make third pass to search for terms 'a' - // that also appears as 'XFa'. Replace them - // by 'Fa' and delete XFa. - for (unsigned n = 0; n < mos; ++n) - { - formula x = res[n]; - if (!x) - continue; - fset_t::const_iterator f = xfset.find(x); - if (f != xfset.end()) - { - // x can appear only once. - formula ff = *f; - xfset.erase(f); - res[n] = formula::F(x); - // We don't need to kill "a" anymore. - tokill[n] = false; - } - } - // Kill any remaining "a", used to simplify Xa R b - // or Xa M b. - for (unsigned n = 0; n < mos; ++n) - if (tokill[n] && res[n]) - res[n] = nullptr; + // If we can remove all of them... + if (allofthem == 0) + // Make third pass to search for terms 'a' + // that also appears as 'XFa'. Replace them + // by 'Fa' and delete XFa. + for (unsigned n = 0; n < mos; ++n) + { + formula x = res[n]; + if (!x) + continue; + fset_t::const_iterator f = xfset.find(x); + if (f != xfset.end()) + { + // x can appear only once. + formula ff = *f; + xfset.erase(f); + res[n] = formula::F(x); + // We don't need to kill "a" anymore. + tokill[n] = false; + } + } + // Kill any remaining "a", used to simplify Xa R b + // or Xa M b. + for (unsigned n = 0; n < mos; ++n) + if (tokill[n] && res[n]) + res[n] = nullptr; - // Now rebuild the formula that remains. - vec xv; - size_t xfs = xfset.size(); - xv.reserve(xset.size() + 1); - if (xfs > 0) - { - // Group all XF(a)|XF(b|c|...)|... as XF(a|b|c|...) - vec xfv; - xfv.reserve(xfs); - for (auto f: xfset) - xfv.push_back(f); - xv.push_back(unop_multop(op::F, op::Or, xfv)); - } - // Also gather the remaining Xa | X(b|c) as X(b|c). - for (auto f: xset) - xv.push_back(f); - res.push_back(unop_multop(op::X, op::Or, xv)); - } + // Now rebuild the formula that remains. + vec xv; + size_t xfs = xfset.size(); + xv.reserve(xset.size() + 1); + if (xfs > 0) + { + // Group all XF(a)|XF(b|c|...)|... as XF(a|b|c|...) + vec xfv; + xfv.reserve(xfs); + for (auto f: xfset) + xfv.push_back(f); + xv.push_back(unop_multop(op::F, op::Or, xfv)); + } + // Also gather the remaining Xa | X(b|c) as X(b|c). + for (auto f: xset) + xv.push_back(f); + res.push_back(unop_multop(op::X, op::Or, xv)); + } - // Gather all operand by type. - mospliter s(mospliter::Strip_X | - mospliter::Strip_GF | - mospliter::Strip_F | - mospliter::Split_G | - mospliter::Split_U_or_W | - mospliter::Split_R_or_M | - mospliter::Split_EventUniv, - res, c_); - // GF(a) | GF(b) = GF(a | b) - formula allGF = unop_unop_multop(op::G, op::F, op::Or, - std::move(*s.res_GF)); + // Gather all operand by type. + mospliter s(mospliter::Strip_X | + mospliter::Strip_GF | + mospliter::Strip_F | + mospliter::Split_G | + mospliter::Split_U_or_W | + mospliter::Split_R_or_M | + mospliter::Split_EventUniv, + res, c_); + // GF(a) | GF(b) = GF(a | b) + formula allGF = unop_unop_multop(op::G, op::F, op::Or, + std::move(*s.res_GF)); - // Xa | Xb = X(a | b) - // Xa | Xb | GF(c) = X(a | b | GF(c)) - // For Universal&Eventual formula f1...fn we also have: - // Xa | Xb | f1...fn = X(a | b | f1...fn) - if (!s.res_X->empty() && !opt_.favor_event_univ) - { - s.res_X->push_back(allGF); - allGF = nullptr; - s.res_X->insert(s.res_X->end(), - s.res_EventUniv->begin(), - s.res_EventUniv->end()); - } - else if (!opt_.favor_event_univ - && !s.res_F->empty() - && s.res_G->empty() - && s.res_U_or_W->empty() - && s.res_R_or_M->empty() - && s.res_other->empty()) - { - // If there is no X but some F and only - // eventual&universal formulae f1...fn|GF(c), do: - // Fa|Fb|f1...fn|GF(c) = F(a|b|f1...fn|GF(c)) - // - // The reasoning here is that if we should - // move f1...fn|GF(c) inside the "F" only - // if it allows us to move all terms under F, - // allowing a nice initial self-loop. - // - // For instance: - // F(a|GFb) 3st.6tr. with initial self-loop - // Fa|GFb 4st.8tr. without initial self-loop - // - // However, if other terms are presents they will - // prevent the formation of a self-loop, and the - // rewriting is unwelcome: - // F(a|GFb)|Gc 5st.11tr. without initial self-loop - // Fa|GFb|Gc 5st.10tr. without initial self-loop - // (counting the number of "subtransitions" - // or, degeneralizing the automaton amplifies - // these differences) - s.res_F->push_back(allGF); - allGF = nullptr; - s.res_F->insert(s.res_F->end(), - s.res_EventUniv->begin(), - s.res_EventUniv->end()); - } - else if (opt_.favor_event_univ) - { - s.res_EventUniv->push_back(allGF); - allGF = nullptr; - bool seen_f = false; - if (s.res_EventUniv->size() > 1) - { - // If some of the EventUniv formulae start - // with an F, Gather them all under the - // same F. Striping any leading F. - for (auto& f: *s.res_EventUniv) - if (f.is(op::F)) - { - seen_f = true; - f = f[0]; - } - if (seen_f) - { - formula eu = - unop_multop(op::F, op::Or, - std::move(*s.res_EventUniv)); - s.res_other->push_back(eu); - } - } - if (!seen_f) - s.res_other->insert(s.res_other->end(), - s.res_EventUniv->begin(), - s.res_EventUniv->end()); - } - else - { - s.res_other->insert(s.res_other->end(), - s.res_EventUniv->begin(), - s.res_EventUniv->end()); - } - // Xa | Xb | f1...fn = X(a | b | f1...fn) - // is built at the end of this multop::Or case. - // F(a) | F(b) = F(a | b) - // is built at the end of this multop::Or case. + // Xa | Xb = X(a | b) + // Xa | Xb | GF(c) = X(a | b | GF(c)) + // For Universal&Eventual formula f1...fn we also have: + // Xa | Xb | f1...fn = X(a | b | f1...fn) + if (!s.res_X->empty() && !opt_.favor_event_univ) + { + s.res_X->push_back(allGF); + allGF = nullptr; + s.res_X->insert(s.res_X->end(), + s.res_EventUniv->begin(), + s.res_EventUniv->end()); + } + else if (!opt_.favor_event_univ + && !s.res_F->empty() + && s.res_G->empty() + && s.res_U_or_W->empty() + && s.res_R_or_M->empty() + && s.res_other->empty()) + { + // If there is no X but some F and only + // eventual&universal formulae f1...fn|GF(c), do: + // Fa|Fb|f1...fn|GF(c) = F(a|b|f1...fn|GF(c)) + // + // The reasoning here is that if we should + // move f1...fn|GF(c) inside the "F" only + // if it allows us to move all terms under F, + // allowing a nice initial self-loop. + // + // For instance: + // F(a|GFb) 3st.6tr. with initial self-loop + // Fa|GFb 4st.8tr. without initial self-loop + // + // However, if other terms are presents they will + // prevent the formation of a self-loop, and the + // rewriting is unwelcome: + // F(a|GFb)|Gc 5st.11tr. without initial self-loop + // Fa|GFb|Gc 5st.10tr. without initial self-loop + // (counting the number of "subtransitions" + // or, degeneralizing the automaton amplifies + // these differences) + s.res_F->push_back(allGF); + allGF = nullptr; + s.res_F->insert(s.res_F->end(), + s.res_EventUniv->begin(), + s.res_EventUniv->end()); + } + else if (opt_.favor_event_univ) + { + s.res_EventUniv->push_back(allGF); + allGF = nullptr; + bool seen_f = false; + if (s.res_EventUniv->size() > 1) + { + // If some of the EventUniv formulae start + // with an F, Gather them all under the + // same F. Striping any leading F. + for (auto& f: *s.res_EventUniv) + if (f.is(op::F)) + { + seen_f = true; + f = f[0]; + } + if (seen_f) + { + formula eu = + unop_multop(op::F, op::Or, + std::move(*s.res_EventUniv)); + s.res_other->push_back(eu); + } + } + if (!seen_f) + s.res_other->insert(s.res_other->end(), + s.res_EventUniv->begin(), + s.res_EventUniv->end()); + } + else + { + s.res_other->insert(s.res_other->end(), + s.res_EventUniv->begin(), + s.res_EventUniv->end()); + } + // Xa | Xb | f1...fn = X(a | b | f1...fn) + // is built at the end of this multop::Or case. + // F(a) | F(b) = F(a | b) + // is built at the end of this multop::Or case. - // The following three loops perform these rewritings: - // (a U b) | (a U c) = a U (b | c) - // (a W b) | (a U c) = a W (b | c) - // (a W b) | (a W c) = a W (b | c) - // (a R b) | (c R b) = (a | c) R b - // (a R b) | (c M b) = (a | c) R b - // (a M b) | (c M b) = (a | c) M b - // G(a) | (a U b) = a W b - // G(a) | (a W b) = a W b - // G(b) | (a R b) = a R b. - // G(b) | (a M b) = a R b. - typedef std::unordered_map fmap_t; - fmap_t uwmap; // associates "a" to "a U b" or "a W b" - fmap_t rmmap; // associates "b" to "a R b" or "a M b" - // (a U b) | (a U c) = a U (b | c) - // (a W b) | (a U c) = a W (b | c) - // (a W b) | (a W c) = a W (b | c) - for (auto i = s.res_U_or_W->begin(); - i != s.res_U_or_W->end(); ++i) - { - formula a = (*i)[0]; - auto j = uwmap.find(a); - if (j == uwmap.end()) - { - // First occurrence. - uwmap[a] = i; - continue; - } - // We already have one occurrence. Merge them. - formula old = *j->second; - op o = op::U; - if (i->is(op::W) || old.is(op::W)) - o = op::W; - formula snd_arg = formula::Or({old[1], (*i)[1]}); - *j->second = formula::binop(o, a, snd_arg); - assert(j->second->is(o)); - *i = nullptr; - } - // (a R b) | (c R b) = (a | c) R b - // (a R b) | (c M b) = (a | c) R b - // (a M b) | (c M b) = (a | c) M b - for (auto i = s.res_R_or_M->begin(); - i != s.res_R_or_M->end(); ++i) - { - formula b = (*i)[1]; - auto j = rmmap.find(b); - if (j == rmmap.end()) - { - // First occurrence. - rmmap[b] = i; - continue; - } - // We already have one occurrence. Merge them. - formula old = *j->second; - op o = op::M; - if (i->is(op::R) || old.is(op::R)) - o = op::R; - formula fst_arg = formula::Or({old[0], (*i)[0]}); - *j->second = formula::binop(o, fst_arg, b); - assert(j->second->is(o)); - *i = nullptr; - } - // G(a) | (a U b) = a W b - // G(a) | (a W b) = a W b - // G(b) | (a R b) = a R b. - // G(b) | (a M b) = a R b. - for (auto& f: *s.res_G) - { - bool superfluous = false; - formula c = f[0]; + // The following three loops perform these rewritings: + // (a U b) | (a U c) = a U (b | c) + // (a W b) | (a U c) = a W (b | c) + // (a W b) | (a W c) = a W (b | c) + // (a R b) | (c R b) = (a | c) R b + // (a R b) | (c M b) = (a | c) R b + // (a M b) | (c M b) = (a | c) M b + // G(a) | (a U b) = a W b + // G(a) | (a W b) = a W b + // G(b) | (a R b) = a R b. + // G(b) | (a M b) = a R b. + typedef std::unordered_map fmap_t; + fmap_t uwmap; // associates "a" to "a U b" or "a W b" + fmap_t rmmap; // associates "b" to "a R b" or "a M b" + // (a U b) | (a U c) = a U (b | c) + // (a W b) | (a U c) = a W (b | c) + // (a W b) | (a W c) = a W (b | c) + for (auto i = s.res_U_or_W->begin(); + i != s.res_U_or_W->end(); ++i) + { + formula a = (*i)[0]; + auto j = uwmap.find(a); + if (j == uwmap.end()) + { + // First occurrence. + uwmap[a] = i; + continue; + } + // We already have one occurrence. Merge them. + formula old = *j->second; + op o = op::U; + if (i->is(op::W) || old.is(op::W)) + o = op::W; + formula snd_arg = formula::Or({old[1], (*i)[1]}); + *j->second = formula::binop(o, a, snd_arg); + assert(j->second->is(o)); + *i = nullptr; + } + // (a R b) | (c R b) = (a | c) R b + // (a R b) | (c M b) = (a | c) R b + // (a M b) | (c M b) = (a | c) M b + for (auto i = s.res_R_or_M->begin(); + i != s.res_R_or_M->end(); ++i) + { + formula b = (*i)[1]; + auto j = rmmap.find(b); + if (j == rmmap.end()) + { + // First occurrence. + rmmap[b] = i; + continue; + } + // We already have one occurrence. Merge them. + formula old = *j->second; + op o = op::M; + if (i->is(op::R) || old.is(op::R)) + o = op::R; + formula fst_arg = formula::Or({old[0], (*i)[0]}); + *j->second = formula::binop(o, fst_arg, b); + assert(j->second->is(o)); + *i = nullptr; + } + // G(a) | (a U b) = a W b + // G(a) | (a W b) = a W b + // G(b) | (a R b) = a R b. + // G(b) | (a M b) = a R b. + for (auto& f: *s.res_G) + { + bool superfluous = false; + formula c = f[0]; - fmap_t::iterator j = uwmap.find(c); - if (j != uwmap.end()) - { - superfluous = true; - formula bo = *j->second; - if (bo.is(op::U)) - { - *j->second = formula::W(bo[0], bo[1]); - assert(j->second->is(op::W)); - } - } - j = rmmap.find(c); - if (j != rmmap.end()) - { - superfluous = true; - formula bo = *j->second; - if (bo.is(op::M)) - { - *j->second = formula::R(bo[0], bo[1]); - assert(j->second->is(op::R)); - } - } - if (superfluous) - f = nullptr; - } + fmap_t::iterator j = uwmap.find(c); + if (j != uwmap.end()) + { + superfluous = true; + formula bo = *j->second; + if (bo.is(op::U)) + { + *j->second = formula::W(bo[0], bo[1]); + assert(j->second->is(op::W)); + } + } + j = rmmap.find(c); + if (j != rmmap.end()) + { + superfluous = true; + formula bo = *j->second; + if (bo.is(op::M)) + { + *j->second = formula::R(bo[0], bo[1]); + assert(j->second->is(op::R)); + } + } + if (superfluous) + f = nullptr; + } - s.res_other->reserve(s.res_other->size() - + s.res_G->size() - + s.res_U_or_W->size() - + s.res_R_or_M->size() - + 3); - s.res_other->insert(s.res_other->end(), - s.res_G->begin(), - s.res_G->end()); - s.res_other->insert(s.res_other->end(), - s.res_U_or_W->begin(), - s.res_U_or_W->end()); - s.res_other->insert(s.res_other->end(), - s.res_R_or_M->begin(), - s.res_R_or_M->end()); + s.res_other->reserve(s.res_other->size() + + s.res_G->size() + + s.res_U_or_W->size() + + s.res_R_or_M->size() + + 3); + s.res_other->insert(s.res_other->end(), + s.res_G->begin(), + s.res_G->end()); + s.res_other->insert(s.res_other->end(), + s.res_U_or_W->begin(), + s.res_U_or_W->end()); + s.res_other->insert(s.res_other->end(), + s.res_R_or_M->begin(), + s.res_R_or_M->end()); - // Those "F" formulae that are universal can be - // postponed inside the X term if there is one. - // - // In effect we rewrite - // Xa|Xb|FGc|FGd|Fe as X(a|b|F(Gc|Gd))|Fe - if (!s.res_X->empty()) - { - vec univ; - for (auto& f: *s.res_F) - if (f.is_universal()) - { - univ.push_back(f); - f = nullptr; // Remove it from res_F. - } - s.res_X->push_back(unop_multop(op::F, op::Or, - std::move(univ))); - } + // Those "F" formulae that are universal can be + // postponed inside the X term if there is one. + // + // In effect we rewrite + // Xa|Xb|FGc|FGd|Fe as X(a|b|F(Gc|Gd))|Fe + if (!s.res_X->empty()) + { + vec univ; + for (auto& f: *s.res_F) + if (f.is_universal()) + { + univ.push_back(f); + f = nullptr; // Remove it from res_F. + } + s.res_X->push_back(unop_multop(op::F, op::Or, + std::move(univ))); + } - // F(a) | F(b) | ... = F(a | b | ...) - formula allF = unop_multop(op::F, op::Or, - std::move(*s.res_F)); - // Xa | Xb | ... = X(a | b | ...) - formula allX = unop_multop(op::X, op::Or, - std::move(*s.res_X)); - s.res_other->push_back(allX); - s.res_other->push_back(allF); - s.res_other->push_back(allGF); - formula r = formula::Or(std::move(*s.res_other)); - // If we altered the formula in some way, process - // it another time. - if (r != mo) - return recurse(r); - return r; - } - case op::AndNLM: - { - mospliter s(mospliter::Split_Bool, res, c_); - if (!s.res_Bool->empty()) - { - // b1 & b2 & b3 = b1 ∧ b2 ∧ b3 - formula b = formula::And(std::move(*s.res_Bool)); + // F(a) | F(b) | ... = F(a | b | ...) + formula allF = unop_multop(op::F, op::Or, + std::move(*s.res_F)); + // Xa | Xb | ... = X(a | b | ...) + formula allX = unop_multop(op::X, op::Or, + std::move(*s.res_X)); + s.res_other->push_back(allX); + s.res_other->push_back(allF); + s.res_other->push_back(allGF); + formula r = formula::Or(std::move(*s.res_other)); + // If we altered the formula in some way, process + // it another time. + if (r != mo) + return recurse(r); + return r; + } + case op::AndNLM: + { + mospliter s(mospliter::Split_Bool, res, c_); + if (!s.res_Bool->empty()) + { + // b1 & b2 & b3 = b1 ∧ b2 ∧ b3 + formula b = formula::And(std::move(*s.res_Bool)); - // now we just consider b & rest - formula rest = formula::AndNLM(std::move(*s.res_other)); + // now we just consider b & rest + formula rest = formula::AndNLM(std::move(*s.res_other)); - // We have b & rest = b : rest if rest does not - // accept [*0]. Otherwise b & rest = b | (b : rest) - // FIXME: It would be nice to remove [*0] from rest. - formula r = nullptr; - if (rest.accepts_eword()) - { - // The b & rest = b | (b : rest) rewriting - // augment the size, so do that only when - // explicitly requested. - if (!opt_.reduce_size_strictly) - return recurse(formula::OrRat - ({b, formula::Fusion({b, rest})})); - else - return mo; - } - else - { - return recurse(formula::Fusion({b, rest})); - } - } - // No Boolean as argument of &&. + // We have b & rest = b : rest if rest does not + // accept [*0]. Otherwise b & rest = b | (b : rest) + // FIXME: It would be nice to remove [*0] from rest. + formula r = nullptr; + if (rest.accepts_eword()) + { + // The b & rest = b | (b : rest) rewriting + // augment the size, so do that only when + // explicitly requested. + if (!opt_.reduce_size_strictly) + return recurse(formula::OrRat + ({b, formula::Fusion({b, rest})})); + else + return mo; + } + else + { + return recurse(formula::Fusion({b, rest})); + } + } + // No Boolean as argument of &&. - // Look for occurrences of {b;r} or {b:r}. We have - // {b1;r1}&{b2;r2} = {b1∧b2};{r1&r2} - // head1 tail1 - // {b1:r1}&{b2:r2} = {b1∧b2}:{r1&r2} - // head2 tail2 - // BEWARE: The second rule is correct only when - // both r1 and r2 do not accept [*0]. + // Look for occurrences of {b;r} or {b:r}. We have + // {b1;r1}&{b2;r2} = {b1∧b2};{r1&r2} + // head1 tail1 + // {b1:r1}&{b2:r2} = {b1∧b2}:{r1&r2} + // head2 tail2 + // BEWARE: The second rule is correct only when + // both r1 and r2 do not accept [*0]. - vec head1; - vec tail1; - vec head2; - vec tail2; - for (auto& i: *s.res_other) - { - if (!i) - continue; - if (!i.is(op::Concat, op::Fusion)) - continue; - formula h = i[0]; - if (!h.is_boolean()) - continue; - if (i.is(op::Concat)) - { - head1.push_back(h); - tail1.push_back(i.all_but(0)); - } - else // op::Fusion - { - formula t = i.all_but(0); - if (t.accepts_eword()) - continue; - head2.push_back(h); - tail2.push_back(t); - } - i = nullptr; - } - if (!head1.empty()) - { - formula h = formula::And(std::move(head1)); - formula t = formula::AndNLM(std::move(tail1)); - s.res_other->push_back(formula::Concat({h, t})); - } - if (!head2.empty()) - { - formula h = formula::And(std::move(head2)); - formula t = formula::AndNLM(std::move(tail2)); - s.res_other->push_back(formula::Fusion({h, t})); - } + vec head1; + vec tail1; + vec head2; + vec tail2; + for (auto& i: *s.res_other) + { + if (!i) + continue; + if (!i.is(op::Concat, op::Fusion)) + continue; + formula h = i[0]; + if (!h.is_boolean()) + continue; + if (i.is(op::Concat)) + { + head1.push_back(h); + tail1.push_back(i.all_but(0)); + } + else // op::Fusion + { + formula t = i.all_but(0); + if (t.accepts_eword()) + continue; + head2.push_back(h); + tail2.push_back(t); + } + i = nullptr; + } + if (!head1.empty()) + { + formula h = formula::And(std::move(head1)); + formula t = formula::AndNLM(std::move(tail1)); + s.res_other->push_back(formula::Concat({h, t})); + } + if (!head2.empty()) + { + formula h = formula::And(std::move(head2)); + formula t = formula::AndNLM(std::move(tail2)); + s.res_other->push_back(formula::Fusion({h, t})); + } - formula r = formula::AndNLM(std::move(*s.res_other)); - // If we altered the formula in some way, process - // it another time. - if (r != mo) - return recurse(r); - return r; - } - case op::OrRat: - case op::Concat: - case op::Fusion: - // FIXME: No simplifications yet. - return mo; - default: - SPOT_UNIMPLEMENTED(); - return nullptr; - } - SPOT_UNREACHABLE(); - } - return mo; + formula r = formula::AndNLM(std::move(*s.res_other)); + // If we altered the formula in some way, process + // it another time. + if (r != mo) + return recurse(r); + return r; + } + case op::OrRat: + case op::Concat: + case op::Fusion: + // FIXME: No simplifications yet. + return mo; + default: + SPOT_UNIMPLEMENTED(); + return nullptr; + } + SPOT_UNREACHABLE(); + } + return mo; } protected: @@ -2980,46 +2980,46 @@ namespace spot formula simplify_recursively(formula f, - tl_simplifier_cache* c) + tl_simplifier_cache* c) { #ifdef TRACE static int srec = 0; for (int i = srec; i; --i) - trace << ' '; + trace << ' '; trace << "** simplify_recursively(" << str_psl(f) << ')'; #endif formula result = c->lookup_simplified(f); if (result) - { - trace << " cached: " << str_psl(result) << std::endl; - return result; - } + { + trace << " cached: " << str_psl(result) << std::endl; + return result; + } else - { - trace << " miss" << std::endl; - } + { + trace << " miss" << std::endl; + } #ifdef TRACE ++srec; #endif if (f.is_boolean() && c->options.boolean_to_isop) - { - result = c->boolean_to_isop(f); - } + { + result = c->boolean_to_isop(f); + } else - { - simplify_visitor v(c); - result = v.visit(f); - } + { + simplify_visitor v(c); + result = v.visit(f); + } #ifdef TRACE --srec; for (int i = srec; i; --i) - trace << ' '; + trace << ' '; trace << "** simplify_recursively(" << str_psl(f) << ") result: " - << str_psl(result) << std::endl; + << str_psl(result) << std::endl; #endif c->cache_simplified(f, result); @@ -3048,238 +3048,238 @@ namespace spot if (!f.is_boolean()) // Deal with all lines of the table except the first two. switch (f.kind()) - { - case op::X: - if (g.is_eventual() && syntactic_implication(f[0], g)) - return true; - if (g.is(op::X) && syntactic_implication(f[0], g[0])) - return true; - break; + { + case op::X: + if (g.is_eventual() && syntactic_implication(f[0], g)) + return true; + if (g.is(op::X) && syntactic_implication(f[0], g[0])) + return true; + break; - case op::F: - if (g.is_eventual() && syntactic_implication(f[0], g)) - return true; - break; + case op::F: + if (g.is_eventual() && syntactic_implication(f[0], g)) + return true; + break; - case op::G: - if (g.is(op::U, op::R) && syntactic_implication(f[0], g[1])) - return true; - if (g.is(op::W) && (syntactic_implication(f[0], g[0]) - || syntactic_implication(f[0], g[1]))) - return true; - if (g.is(op::M) && (syntactic_implication(f[0], g[0]) - && syntactic_implication(f[0], g[1]))) - return true; - // First column. - if (syntactic_implication(f[0], g)) - return true; - break; + case op::G: + if (g.is(op::U, op::R) && syntactic_implication(f[0], g[1])) + return true; + if (g.is(op::W) && (syntactic_implication(f[0], g[0]) + || syntactic_implication(f[0], g[1]))) + return true; + if (g.is(op::M) && (syntactic_implication(f[0], g[0]) + && syntactic_implication(f[0], g[1]))) + return true; + // First column. + if (syntactic_implication(f[0], g)) + return true; + break; - case op::U: - { - formula f1 = f[0]; - formula f2 = f[1]; - if (g.is(op::U, op::W) - && syntactic_implication(f1, g[0]) - && syntactic_implication(f2, g[1])) - return true; - if (g.is(op::M, op::R) - && syntactic_implication(f1, g[1]) - && syntactic_implication(f2, g[0]) - && syntactic_implication(f2, g[1])) - return true; - if (g.is(op::F) && syntactic_implication(f2, g[0])) - return true; - // First column. - if (syntactic_implication(f1, g) && syntactic_implication(f2, g)) - return true; - break; - } - case op::W: - { - formula f1 = f[0]; - formula f2 = f[1]; - if (g.is(op::U) && (syntactic_implication(f1, g[1]) - && syntactic_implication(f2, g[1]))) - return true; - if (g.is(op::W) && (syntactic_implication(f1, g[0]) - && syntactic_implication(f2, g[1]))) - return true; - if (g.is(op::R) && (syntactic_implication(f1, g[1]) - && syntactic_implication(f2, g[0]) - && syntactic_implication(f2, g[1]))) - return true; - if (g.is(op::F) && (syntactic_implication(f1, g[0]) - && syntactic_implication(f2, g[0]))) - return true; - // First column. - if (syntactic_implication(f1, g) && syntactic_implication(f2, g)) - return true; - break; - } - case op::R: - { - formula f1 = f[0]; - formula f2 = f[1]; - if (g.is(op::W) && (syntactic_implication(f1, g[1]) - && syntactic_implication(f2, g[0]))) - return true; - if (g.is(op::R) && (syntactic_implication(f1, g[0]) - && syntactic_implication(f2, g[1]))) - return true; - if (g.is(op::M) && (syntactic_implication(f2, g[0]) - && syntactic_implication(f2, g[1]))) - return true; - if (g.is(op::F) && syntactic_implication(f2, g[0])) - return true; - // First column. - if (syntactic_implication(f2, g)) - return true; - break; - } - case op::M: - { - formula f1 = f[0]; - formula f2 = f[1]; - if (g.is(op::U, op::W) && (syntactic_implication(f1, g[1]) - && syntactic_implication(f2, - g[0]))) - return true; - if (g.is(op::R, op::M) && (syntactic_implication(f1, g[0]) - && syntactic_implication(f2, - g[1]))) - return true; - if (g.is(op::F) && (syntactic_implication(f1, g[0]) - || syntactic_implication(f2, g[0]))) - return true; - // First column. - if (syntactic_implication(f2, g)) - return true; - break; - } - case op::Or: - { - // If we are checking something like - // (a | b | Xc) => g, - // split it into - // (a | b) => g - // Xc => g - unsigned i = 0; - if (formula bops = f.boolean_operands(&i)) - if (!syntactic_implication(bops, g)) - break; - bool b = true; - unsigned fs = f.size(); - for (; i < fs; ++i) - if (!syntactic_implication(f[i], g)) - { - b = false; - break; - } - if (b) - return true; - break; - } - case op::And: - { - // If we are checking something like - // (a & b & Xc) => g, - // split it into - // (a & b) => g - // Xc => g - unsigned i = 0; - if (formula bops = f.boolean_operands(&i)) - if (syntactic_implication(bops, g)) - return true; - unsigned fs = f.size(); - for (; i < fs; ++i) - if (syntactic_implication(f[i], g)) - return true; - break; - } - default: - break; - } + case op::U: + { + formula f1 = f[0]; + formula f2 = f[1]; + if (g.is(op::U, op::W) + && syntactic_implication(f1, g[0]) + && syntactic_implication(f2, g[1])) + return true; + if (g.is(op::M, op::R) + && syntactic_implication(f1, g[1]) + && syntactic_implication(f2, g[0]) + && syntactic_implication(f2, g[1])) + return true; + if (g.is(op::F) && syntactic_implication(f2, g[0])) + return true; + // First column. + if (syntactic_implication(f1, g) && syntactic_implication(f2, g)) + return true; + break; + } + case op::W: + { + formula f1 = f[0]; + formula f2 = f[1]; + if (g.is(op::U) && (syntactic_implication(f1, g[1]) + && syntactic_implication(f2, g[1]))) + return true; + if (g.is(op::W) && (syntactic_implication(f1, g[0]) + && syntactic_implication(f2, g[1]))) + return true; + if (g.is(op::R) && (syntactic_implication(f1, g[1]) + && syntactic_implication(f2, g[0]) + && syntactic_implication(f2, g[1]))) + return true; + if (g.is(op::F) && (syntactic_implication(f1, g[0]) + && syntactic_implication(f2, g[0]))) + return true; + // First column. + if (syntactic_implication(f1, g) && syntactic_implication(f2, g)) + return true; + break; + } + case op::R: + { + formula f1 = f[0]; + formula f2 = f[1]; + if (g.is(op::W) && (syntactic_implication(f1, g[1]) + && syntactic_implication(f2, g[0]))) + return true; + if (g.is(op::R) && (syntactic_implication(f1, g[0]) + && syntactic_implication(f2, g[1]))) + return true; + if (g.is(op::M) && (syntactic_implication(f2, g[0]) + && syntactic_implication(f2, g[1]))) + return true; + if (g.is(op::F) && syntactic_implication(f2, g[0])) + return true; + // First column. + if (syntactic_implication(f2, g)) + return true; + break; + } + case op::M: + { + formula f1 = f[0]; + formula f2 = f[1]; + if (g.is(op::U, op::W) && (syntactic_implication(f1, g[1]) + && syntactic_implication(f2, + g[0]))) + return true; + if (g.is(op::R, op::M) && (syntactic_implication(f1, g[0]) + && syntactic_implication(f2, + g[1]))) + return true; + if (g.is(op::F) && (syntactic_implication(f1, g[0]) + || syntactic_implication(f2, g[0]))) + return true; + // First column. + if (syntactic_implication(f2, g)) + return true; + break; + } + case op::Or: + { + // If we are checking something like + // (a | b | Xc) => g, + // split it into + // (a | b) => g + // Xc => g + unsigned i = 0; + if (formula bops = f.boolean_operands(&i)) + if (!syntactic_implication(bops, g)) + break; + bool b = true; + unsigned fs = f.size(); + for (; i < fs; ++i) + if (!syntactic_implication(f[i], g)) + { + b = false; + break; + } + if (b) + return true; + break; + } + case op::And: + { + // If we are checking something like + // (a & b & Xc) => g, + // split it into + // (a & b) => g + // Xc => g + unsigned i = 0; + if (formula bops = f.boolean_operands(&i)) + if (syntactic_implication(bops, g)) + return true; + unsigned fs = f.size(); + for (; i < fs; ++i) + if (syntactic_implication(f[i], g)) + return true; + break; + } + default: + break; + } // First two lines of the table. // (Don't check equality, it has already be done.) if (!g.is_boolean()) switch (g.kind()) - { - case op::F: - if (syntactic_implication(f, g[0])) - return true; - break; + { + case op::F: + if (syntactic_implication(f, g[0])) + return true; + break; - case op::G: - case op::X: - if (f.is_universal() && syntactic_implication(f, g[0])) - return true; - break; + case op::G: + case op::X: + if (f.is_universal() && syntactic_implication(f, g[0])) + return true; + break; - case op::U: - case op::W: - if (syntactic_implication(f, g[1])) - return true; - break; + case op::U: + case op::W: + if (syntactic_implication(f, g[1])) + return true; + break; - case op::M: - case op::R: - if (syntactic_implication(f, g[0]) - && syntactic_implication(f, g[1])) - return true; - break; + case op::M: + case op::R: + if (syntactic_implication(f, g[0]) + && syntactic_implication(f, g[1])) + return true; + break; - case op::And: - { - // If we are checking something like - // f => (a & b & Xc), - // split it into - // f => (a & b) - // f => Xc - unsigned i = 0; - if (formula bops = g.boolean_operands(&i)) - if (!syntactic_implication(f, bops)) - break; - bool b = true; - unsigned gs = g.size(); - for (; i < gs; ++i) - if (!syntactic_implication(f, g[i])) - { - b = false; - break; - } - if (b) - return true; - break; - } + case op::And: + { + // If we are checking something like + // f => (a & b & Xc), + // split it into + // f => (a & b) + // f => Xc + unsigned i = 0; + if (formula bops = g.boolean_operands(&i)) + if (!syntactic_implication(f, bops)) + break; + bool b = true; + unsigned gs = g.size(); + for (; i < gs; ++i) + if (!syntactic_implication(f, g[i])) + { + b = false; + break; + } + if (b) + return true; + break; + } - case op::Or: - { - // If we are checking something like - // f => (a | b | Xc), - // split it into - // f => (a | b) - // f => Xc - unsigned i = 0; - if (formula bops = g.boolean_operands(&i)) - if (syntactic_implication(f, bops)) - return true; - unsigned gs = g.size(); - for (; i < gs; ++i) - if (syntactic_implication(f, g[i])) - return true; - break; - } - default: - break; - } + case op::Or: + { + // If we are checking something like + // f => (a | b | Xc), + // split it into + // f => (a | b) + // f => Xc + unsigned i = 0; + if (formula bops = g.boolean_operands(&i)) + if (syntactic_implication(f, bops)) + return true; + unsigned gs = g.size(); + for (; i < gs; ++i) + if (syntactic_implication(f, g[i])) + return true; + break; + } + default: + break; + } return false; } // Return true if f => g syntactically bool tl_simplifier_cache::syntactic_implication(formula f, - formula g) + formula g) { // We cannot run syntactic_implication on SERE formulae, // except on Boolean formulae. @@ -3307,7 +3307,7 @@ namespace spot pairf p(f, g); syntimpl_cache_t::const_iterator i = syntimpl_.find(p); if (i != syntimpl_.end()) - return i->second; + return i->second; } bool result; @@ -3332,8 +3332,8 @@ namespace spot // If right==true, true if f1 => !f2, false otherwise. bool tl_simplifier_cache::syntactic_implication_neg(formula f1, - formula f2, - bool right) + formula f2, + bool right) { // We cannot run syntactic_implication_neg on SERE formulae, // except on Boolean formulae. @@ -3358,7 +3358,7 @@ namespace spot } tl_simplifier::tl_simplifier(const tl_simplifier_options& opt, - bdd_dict_ptr d) + bdd_dict_ptr d) { cache_ = new tl_simplifier_cache(d, opt); } @@ -3390,7 +3390,7 @@ namespace spot bool tl_simplifier::syntactic_implication_neg(formula f1, - formula f2, bool right) + formula f2, bool right) { return cache_->syntactic_implication_neg(f1, f2, right); } diff --git a/spot/tl/simplify.hh b/spot/tl/simplify.hh index bc4c104e5..2af118f81 100644 --- a/spot/tl/simplify.hh +++ b/spot/tl/simplify.hh @@ -30,23 +30,23 @@ namespace spot { public: tl_simplifier_options(bool basics = true, - bool synt_impl = true, - bool event_univ = true, - bool containment_checks = false, - bool containment_checks_stronger = false, - bool nenoform_stop_on_boolean = false, - bool reduce_size_strictly = false, - bool boolean_to_isop = false, - bool favor_event_univ = false) + bool synt_impl = true, + bool event_univ = true, + bool containment_checks = false, + bool containment_checks_stronger = false, + bool nenoform_stop_on_boolean = false, + bool reduce_size_strictly = false, + bool boolean_to_isop = false, + bool favor_event_univ = false) : reduce_basics(basics), - synt_impl(synt_impl), - event_univ(event_univ), - containment_checks(containment_checks), - containment_checks_stronger(containment_checks_stronger), - nenoform_stop_on_boolean(nenoform_stop_on_boolean), - reduce_size_strictly(reduce_size_strictly), - boolean_to_isop(boolean_to_isop), - favor_event_univ(favor_event_univ) + synt_impl(synt_impl), + event_univ(event_univ), + containment_checks(containment_checks), + containment_checks_stronger(containment_checks_stronger), + nenoform_stop_on_boolean(nenoform_stop_on_boolean), + reduce_size_strictly(reduce_size_strictly), + boolean_to_isop(boolean_to_isop), + favor_event_univ(favor_event_univ) { } @@ -54,21 +54,21 @@ namespace spot tl_simplifier_options(false, false, false) { switch (level) - { - case 3: - containment_checks = true; - containment_checks_stronger = true; - // fall through - case 2: - synt_impl = true; - // fall through - case 1: - reduce_basics = true; - event_univ = true; - // fall through - default: - break; - } + { + case 3: + containment_checks = true; + containment_checks_stronger = true; + // fall through + case 2: + synt_impl = true; + // fall through + case 1: + reduce_basics = true; + event_univ = true; + // fall through + default: + break; + } } bool reduce_basics; @@ -99,7 +99,7 @@ namespace spot public: tl_simplifier(const bdd_dict_ptr& dict = make_bdd_dict()); tl_simplifier(const tl_simplifier_options& opt, - bdd_dict_ptr dict = make_bdd_dict()); + bdd_dict_ptr dict = make_bdd_dict()); ~tl_simplifier(); /// Simplify the formula \a f (using options supplied to the @@ -123,18 +123,18 @@ namespace spot /// /// This is adapted from /** \verbatim - @InProceedings{ somenzi.00.cav, - author = {Fabio Somenzi and Roderick Bloem}, - title = {Efficient {B\"u}chi Automata for {LTL} Formulae}, - booktitle = {Proceedings of the 12th International Conference on - Computer Aided Verification (CAV'00)}, - pages = {247--263}, - year = {2000}, - volume = {1855}, - series = {Lecture Notes in Computer Science}, - publisher = {Springer-Verlag} - } - \endverbatim */ + @InProceedings{ somenzi.00.cav, + author = {Fabio Somenzi and Roderick Bloem}, + title = {Efficient {B\"u}chi Automata for {LTL} Formulae}, + booktitle = {Proceedings of the 12th International Conference on + Computer Aided Verification (CAV'00)}, + pages = {247--263}, + year = {2000}, + volume = {1855}, + series = {Lecture Notes in Computer Science}, + publisher = {Springer-Verlag} + } + \endverbatim */ /// bool syntactic_implication(formula f, formula g); /// \brief Syntactic implication with one negated argument. @@ -143,7 +143,7 @@ namespace spot /// \a f implies !\a g. If \a right is false, this returns /// whether !\a f implies \a g. bool syntactic_implication_neg(formula f, formula g, - bool right); + bool right); /// \brief check whether two formulae are equivalent. /// diff --git a/spot/tl/snf.cc b/spot/tl/snf.cc index 2f2e651ef..1ed89accf 100644 --- a/spot/tl/snf.cc +++ b/spot/tl/snf.cc @@ -33,97 +33,97 @@ namespace spot snf_cache* cache_; public: snf_visitor(snf_cache* c) - : cache_(c) + : cache_(c) { } formula visit(formula f) { - if (!f.accepts_eword()) - return f; + if (!f.accepts_eword()) + return f; - snf_cache::const_iterator i = cache_->find(f); - if (i != cache_->end()) - return i->second; + snf_cache::const_iterator i = cache_->find(f); + if (i != cache_->end()) + return i->second; - formula out; - switch (f.kind()) - { - case op::eword: - out = formula::ff(); - break; - case op::Star: - if (!bounded) - out = visit(f[0]); // Strip the star. - else - out = formula::Star(visit(f[0]), - std::max(unsigned(f.min()), 1U), f.max()); - break; - case op::Concat: - if (bounded) - { - out = f; - break; - } - // Fall through - case op::OrRat: - case op::AndNLM: - // Let F designate expressions that accept [*0], - // and G designate expressions that do not. + formula out; + switch (f.kind()) + { + case op::eword: + out = formula::ff(); + break; + case op::Star: + if (!bounded) + out = visit(f[0]); // Strip the star. + else + out = formula::Star(visit(f[0]), + std::max(unsigned(f.min()), 1U), f.max()); + break; + case op::Concat: + if (bounded) + { + out = f; + break; + } + // Fall through + case op::OrRat: + case op::AndNLM: + // Let F designate expressions that accept [*0], + // and G designate expressions that do not. - // (G₁;G₂;G₃)° = G₁;G₂;G₃ - // (G₁;F₂;G₃)° = (G₁°);F₂;(G₃°) = G₁;F₂;G₃ - // because there is nothing to do recursively on a G. - // - // AndNLM can be dealt with similarly. - // - // The above cases are already handled by the - // accepts_eword() tests at the top of this method. So - // we reach this switch, we only have to deal with... - // - // (F₁;F₂;F₃)° = (F₁°)|(F₂°)|(F₃°) - // (F₁&F₂&F₃)° = (F₁°)|(F₂°)|(F₃°) - // (F₁|G₂|F₃)° = (F₁°)|(G₂°)|(F₃°) - { - unsigned s = f.size(); - std::vector v; - v.reserve(s); - for (unsigned pos = 0; pos < s; ++pos) - v.emplace_back(visit(f[pos])); - out = formula::OrRat(v); - break; - } - case op::ff: - case op::tt: - case op::ap: - case op::Not: - case op::X: - case op::F: - case op::G: - case op::Closure: - case op::NegClosure: - case op::NegClosureMarked: - case op::Xor: - case op::Implies: - case op::Equiv: - case op::U: - case op::R: - case op::W: - case op::M: - case op::EConcat: - case op::EConcatMarked: - case op::UConcat: - case op::Fusion: - case op::Or: - case op::And: - SPOT_UNREACHABLE(); - case op::AndRat: // Can AndRat be handled better? - case op::FStar: // Can FStar be handled better? - out = f; - break; - } + // (G₁;G₂;G₃)° = G₁;G₂;G₃ + // (G₁;F₂;G₃)° = (G₁°);F₂;(G₃°) = G₁;F₂;G₃ + // because there is nothing to do recursively on a G. + // + // AndNLM can be dealt with similarly. + // + // The above cases are already handled by the + // accepts_eword() tests at the top of this method. So + // we reach this switch, we only have to deal with... + // + // (F₁;F₂;F₃)° = (F₁°)|(F₂°)|(F₃°) + // (F₁&F₂&F₃)° = (F₁°)|(F₂°)|(F₃°) + // (F₁|G₂|F₃)° = (F₁°)|(G₂°)|(F₃°) + { + unsigned s = f.size(); + std::vector v; + v.reserve(s); + for (unsigned pos = 0; pos < s; ++pos) + v.emplace_back(visit(f[pos])); + out = formula::OrRat(v); + break; + } + case op::ff: + case op::tt: + case op::ap: + case op::Not: + case op::X: + case op::F: + case op::G: + case op::Closure: + case op::NegClosure: + case op::NegClosureMarked: + case op::Xor: + case op::Implies: + case op::Equiv: + case op::U: + case op::R: + case op::W: + case op::M: + case op::EConcat: + case op::EConcatMarked: + case op::UConcat: + case op::Fusion: + case op::Or: + case op::And: + SPOT_UNREACHABLE(); + case op::AndRat: // Can AndRat be handled better? + case op::FStar: // Can FStar be handled better? + out = f; + break; + } - return (*cache_)[f] = out; + return (*cache_)[f] = out; } }; } diff --git a/spot/tl/snf.hh b/spot/tl/snf.hh index d5aee80f6..43d22218e 100644 --- a/spot/tl/snf.hh +++ b/spot/tl/snf.hh @@ -33,13 +33,13 @@ namespace spot /// paper. /// /** \verbatim - @Article{ bruggeman.96.tcs, - author = {Anne Br{\"u}ggemann-Klein}, - title = {Regular Expressions into Finite Automata}, - journal = {Theoretical Computer Science}, - year = {1996}, - volume = {120}, - pages = {87--98} + @Article{ bruggeman.96.tcs, + author = {Anne Br{\"u}ggemann-Klein}, + title = {Regular Expressions into Finite Automata}, + journal = {Theoretical Computer Science}, + year = {1996}, + volume = {120}, + pages = {87--98} } \endverbatim */ /// diff --git a/spot/tl/unabbrev.cc b/spot/tl/unabbrev.cc index 416d0cac6..b5daa5d7c 100644 --- a/spot/tl/unabbrev.cc +++ b/spot/tl/unabbrev.cc @@ -26,44 +26,44 @@ namespace spot { while (*opt) switch (char c = *opt++) - { - case 'e': - re_e_ = true; - re_some_bool_ = true; - break; - case 'F': - re_f_ = true; - re_some_f_g_ = true; - break; - case 'G': - re_g_ = true; - re_some_f_g_ = true; - break; - case 'i': - re_i_ = true; - re_some_bool_ = true; - break; - case 'M': - re_m_ = true; - re_some_other_ = true; - break; - case 'R': - re_r_ = true; - re_some_other_ = true; - break; - case 'W': - re_w_ = true; - re_some_other_ = true; - break; - case '^': - re_xor_ = true; - re_some_bool_ = true; - break; - default: - throw std::runtime_error - (std::string("unknown unabbreviation option: ") - + c); - } + { + case 'e': + re_e_ = true; + re_some_bool_ = true; + break; + case 'F': + re_f_ = true; + re_some_f_g_ = true; + break; + case 'G': + re_g_ = true; + re_some_f_g_ = true; + break; + case 'i': + re_i_ = true; + re_some_bool_ = true; + break; + case 'M': + re_m_ = true; + re_some_other_ = true; + break; + case 'R': + re_r_ = true; + re_some_other_ = true; + break; + case 'W': + re_w_ = true; + re_some_other_ = true; + break; + case '^': + re_xor_ = true; + re_some_bool_ = true; + break; + default: + throw std::runtime_error + (std::string("unknown unabbreviation option: ") + + c); + } } formula unabbreviator::run(formula in) @@ -76,12 +76,12 @@ namespace spot bool no_boolean_rewrite = !re_some_bool_ || in.is_sugar_free_boolean(); bool no_f_g_rewrite = !re_some_f_g_ || in.is_sugar_free_ltl(); if (no_boolean_rewrite - && (in.is_boolean() || (no_f_g_rewrite && !re_some_other_))) + && (in.is_boolean() || (no_f_g_rewrite && !re_some_other_))) return entry.first->second = in; auto rec = [this](formula f) { - return this->run(f); + return this->run(f); }; formula out = in; @@ -112,132 +112,132 @@ namespace spot case op::Fusion: case op::Star: case op::FStar: - break; + break; case op::F: - // F f = true U f - if (!re_f_) - break; - out = formula::U(formula::tt(), out[0]); - break; + // F f = true U f + if (!re_f_) + break; + out = formula::U(formula::tt(), out[0]); + break; case op::G: - // G f = false R f - // G f = f W false - // G f = !F!f - // G f = !(true U !f) - if (!re_g_) - break; - if (!re_r_) - { - out = formula::R(formula::ff(), out[0]); - break; - } - if (!re_w_) - { - out = formula::W(out[0], formula::ff()); - break; - } - { - auto nc = formula::Not(out[0]); - if (!re_f_) - { - out = formula::Not(formula::F(nc)); - break; - } - out = formula::Not(formula::U(formula::tt(), nc)); - break; - } + // G f = false R f + // G f = f W false + // G f = !F!f + // G f = !(true U !f) + if (!re_g_) + break; + if (!re_r_) + { + out = formula::R(formula::ff(), out[0]); + break; + } + if (!re_w_) + { + out = formula::W(out[0], formula::ff()); + break; + } + { + auto nc = formula::Not(out[0]); + if (!re_f_) + { + out = formula::Not(formula::F(nc)); + break; + } + out = formula::Not(formula::U(formula::tt(), nc)); + break; + } case op::Xor: - // f1 ^ f2 == !(f1 <-> f2) - // f1 ^ f2 == (f1 & !f2) | (f2 & !f1) - if (!re_xor_) - break; - { - auto f1 = out[0]; - auto f2 = out[1]; - if (!re_e_) - { - out = formula::Not(formula::Equiv(f1, f2)); - } - else - { - auto a = formula::And({f1, formula::Not(f2)}); - auto b = formula::And({f2, formula::Not(f1)}); - out = formula::Or({a, b}); - } - } - break; + // f1 ^ f2 == !(f1 <-> f2) + // f1 ^ f2 == (f1 & !f2) | (f2 & !f1) + if (!re_xor_) + break; + { + auto f1 = out[0]; + auto f2 = out[1]; + if (!re_e_) + { + out = formula::Not(formula::Equiv(f1, f2)); + } + else + { + auto a = formula::And({f1, formula::Not(f2)}); + auto b = formula::And({f2, formula::Not(f1)}); + out = formula::Or({a, b}); + } + } + break; case op::Implies: - // f1 => f2 == !f1 | f2 - if (!re_i_) - break; - out = formula::Or({formula::Not(out[0]), out[1]}); - break; + // f1 => f2 == !f1 | f2 + if (!re_i_) + break; + out = formula::Or({formula::Not(out[0]), out[1]}); + break; case op::Equiv: - // f1 <=> f2 == (f1 & f2) | (!f1 & !f2) - if (!re_e_) - break; - { - auto f1 = out[0]; - auto f2 = out[1]; - auto nf1 = formula::Not(f1); - auto nf2 = formula::Not(f2); - auto term1 = formula::And({f1, f2}); - auto term2 = formula::And({nf1, nf2}); - out = formula::Or({term1, term2}); - break; - } + // f1 <=> f2 == (f1 & f2) | (!f1 & !f2) + if (!re_e_) + break; + { + auto f1 = out[0]; + auto f2 = out[1]; + auto nf1 = formula::Not(f1); + auto nf2 = formula::Not(f2); + auto term1 = formula::And({f1, f2}); + auto term2 = formula::And({nf1, nf2}); + out = formula::Or({term1, term2}); + break; + } case op::R: - // f1 R f2 = f2 W (f1 & f2) - // f1 R f2 = f2 U ((f1 & f2) | Gf2) - // f1 R f2 = f2 U ((f1 & f2) | !F!f2) - // f1 R f2 = f2 U ((f1 & f2) | !(1 U !f2)) - if (!re_r_) - break; - { - auto f1 = out[0]; - auto f2 = out[1]; - auto f12 = formula::And({f1, f2}); - if (!re_w_) - { - out = formula::W(f2, f12); - break; - } - auto gf2 = formula::G(f2); - if (re_g_) - gf2 = run(gf2); - out = formula::U(f2, formula::Or({f12, gf2})); - break; - } + // f1 R f2 = f2 W (f1 & f2) + // f1 R f2 = f2 U ((f1 & f2) | Gf2) + // f1 R f2 = f2 U ((f1 & f2) | !F!f2) + // f1 R f2 = f2 U ((f1 & f2) | !(1 U !f2)) + if (!re_r_) + break; + { + auto f1 = out[0]; + auto f2 = out[1]; + auto f12 = formula::And({f1, f2}); + if (!re_w_) + { + out = formula::W(f2, f12); + break; + } + auto gf2 = formula::G(f2); + if (re_g_) + gf2 = run(gf2); + out = formula::U(f2, formula::Or({f12, gf2})); + break; + } case op::W: - // f1 W f2 = f2 R (f2 | f1) - // f1 W f2 = f1 U (f2 | G f1) - // f1 W f2 = f1 U (f2 | !F !f1) - // f1 W f2 = f1 U (f2 | !(1 U !f1)) - if (!re_w_) - break; - { - auto f1 = out[0]; - auto f2 = out[1]; - if (!re_r_) - { - out = formula::R(f2, formula::Or({f2, f1})); - break; - } - auto gf1 = formula::G(f1); - if (re_g_) - gf1 = run(gf1); - out = formula::U(f1, formula::Or({f2, gf1})); - break; - } + // f1 W f2 = f2 R (f2 | f1) + // f1 W f2 = f1 U (f2 | G f1) + // f1 W f2 = f1 U (f2 | !F !f1) + // f1 W f2 = f1 U (f2 | !(1 U !f1)) + if (!re_w_) + break; + { + auto f1 = out[0]; + auto f2 = out[1]; + if (!re_r_) + { + out = formula::R(f2, formula::Or({f2, f1})); + break; + } + auto gf1 = formula::G(f1); + if (re_g_) + gf1 = run(gf1); + out = formula::U(f1, formula::Or({f2, gf1})); + break; + } case op::M: - // f1 M f2 = f2 U (g2 & f1) - if (!re_m_) - break; - { - auto f2 = out[1]; - out = formula::U(f2, formula::And({f2, out[0]})); - break; - } + // f1 M f2 = f2 U (g2 & f1) + if (!re_m_) + break; + { + auto f2 = out[1]; + out = formula::U(f2, formula::And({f2, out[0]})); + break; + } } return entry.first->second = out; } diff --git a/spot/tl/unabbrev.hh b/spot/tl/unabbrev.hh index 2e7129633..f691e58ed 100644 --- a/spot/tl/unabbrev.hh +++ b/spot/tl/unabbrev.hh @@ -41,9 +41,9 @@ namespace spot bool re_r_ = false; bool re_w_ = false; bool re_xor_ = false; - bool re_some_bool_ = false; // rewrite xor, i, or e - bool re_some_f_g_ = false; // rewrite F or G - bool re_some_other_ = false; // rewrite W, M, or R + bool re_some_bool_ = false; // rewrite xor, i, or e + bool re_some_f_g_ = false; // rewrite F or G + bool re_some_other_ = false; // rewrite W, M, or R // Cache of rewritten subformulas std::unordered_map cache_; public: diff --git a/spot/twa/acc.cc b/spot/twa/acc.cc index 5cc009b14..01f7f077a 100644 --- a/spot/twa/acc.cc +++ b/spot/twa/acc.cc @@ -39,13 +39,13 @@ namespace spot const char* comma = ""; while (a) { - if (a & 1) - { - os << comma << level; - comma = ","; - } - a >>= 1; - ++level; + if (a & 1) + { + os << comma << level; + comma = ","; + } + a >>= 1; + ++level; } os << '}'; return os; @@ -66,108 +66,108 @@ namespace spot template static void print_code(std::ostream& os, - const acc_cond::acc_code& code, unsigned pos, - std::function set_printer) + const acc_cond::acc_code& code, unsigned pos, + std::function set_printer) { const char* op = " | "; auto& w = code[pos]; const char* negated = ""; bool top = pos == code.size() - 1; switch (w.op) - { - case acc_cond::acc_op::And: - op = html ? " & " : " & "; - case acc_cond::acc_op::Or: - { - unsigned sub = pos - w.size; - if (!top) - os << '('; - bool first = true; - while (sub < pos) - { - --pos; - if (first) - first = false; - else - os << op; - print_code(os, code, pos, set_printer); - pos -= code[pos].size; - } - if (!top) - os << ')'; - } - break; - case acc_cond::acc_op::InfNeg: - negated = "!"; - case acc_cond::acc_op::Inf: - { - auto a = code[pos - 1].mark.id; - if (a == 0U) - { - os << 't'; - } - else - { - if (!top) - // Avoid extra parentheses if there is only one set - top = code[pos - 1].mark.count() == 1; - unsigned level = 0; - const char* and_ = ""; - if (!top) - os << '('; - while (a) - { - if (a & 1) - { - os << and_ << "Inf(" << negated; - set_printer(os, level); - os << ')'; - and_ = html ? "&" : "&"; - } - a >>= 1; - ++level; - } - if (!top) - os << ')'; - } - } - break; - case acc_cond::acc_op::FinNeg: - negated = "!"; - case acc_cond::acc_op::Fin: - { - auto a = code[pos - 1].mark.id; - if (a == 0U) - { - os << 'f'; - } - else - { - if (!top) - // Avoid extra parentheses if there is only one set - top = code[pos - 1].mark.count() == 1; - unsigned level = 0; - const char* or_ = ""; - if (!top) - os << '('; - while (a) - { - if (a & 1) - { - os << or_ << "Fin(" << negated; - set_printer(os, level); - os << ')'; - or_ = "|"; - } - a >>= 1; - ++level; - } - if (!top) - os << ')'; - } - } - break; - } + { + case acc_cond::acc_op::And: + op = html ? " & " : " & "; + case acc_cond::acc_op::Or: + { + unsigned sub = pos - w.size; + if (!top) + os << '('; + bool first = true; + while (sub < pos) + { + --pos; + if (first) + first = false; + else + os << op; + print_code(os, code, pos, set_printer); + pos -= code[pos].size; + } + if (!top) + os << ')'; + } + break; + case acc_cond::acc_op::InfNeg: + negated = "!"; + case acc_cond::acc_op::Inf: + { + auto a = code[pos - 1].mark.id; + if (a == 0U) + { + os << 't'; + } + else + { + if (!top) + // Avoid extra parentheses if there is only one set + top = code[pos - 1].mark.count() == 1; + unsigned level = 0; + const char* and_ = ""; + if (!top) + os << '('; + while (a) + { + if (a & 1) + { + os << and_ << "Inf(" << negated; + set_printer(os, level); + os << ')'; + and_ = html ? "&" : "&"; + } + a >>= 1; + ++level; + } + if (!top) + os << ')'; + } + } + break; + case acc_cond::acc_op::FinNeg: + negated = "!"; + case acc_cond::acc_op::Fin: + { + auto a = code[pos - 1].mark.id; + if (a == 0U) + { + os << 'f'; + } + else + { + if (!top) + // Avoid extra parentheses if there is only one set + top = code[pos - 1].mark.count() == 1; + unsigned level = 0; + const char* or_ = ""; + if (!top) + os << '('; + while (a) + { + if (a & 1) + { + os << or_ << "Fin(" << negated; + set_printer(os, level); + os << ')'; + or_ = "|"; + } + a >>= 1; + ++level; + } + if (!top) + os << ')'; + } + } + break; + } } @@ -175,39 +175,39 @@ namespace spot eval(acc_cond::mark_t inf, const acc_cond::acc_word* pos) { switch (pos->op) - { - case acc_cond::acc_op::And: - { - auto sub = pos - pos->size; - while (sub < pos) - { - --pos; - if (!eval(inf, pos)) - return false; - pos -= pos->size; - } - return true; - } - case acc_cond::acc_op::Or: - { - auto sub = pos - pos->size; - while (sub < pos) - { - --pos; - if (eval(inf, pos)) - return true; - pos -= pos->size; - } - return false; - } - case acc_cond::acc_op::Inf: - return (pos[-1].mark & inf) == pos[-1].mark; - case acc_cond::acc_op::Fin: - return (pos[-1].mark & inf) != pos[-1].mark; - case acc_cond::acc_op::FinNeg: - case acc_cond::acc_op::InfNeg: - SPOT_UNREACHABLE(); - } + { + case acc_cond::acc_op::And: + { + auto sub = pos - pos->size; + while (sub < pos) + { + --pos; + if (!eval(inf, pos)) + return false; + pos -= pos->size; + } + return true; + } + case acc_cond::acc_op::Or: + { + auto sub = pos - pos->size; + while (sub < pos) + { + --pos; + if (eval(inf, pos)) + return true; + pos -= pos->size; + } + return false; + } + case acc_cond::acc_op::Inf: + return (pos[-1].mark & inf) == pos[-1].mark; + case acc_cond::acc_op::Fin: + return (pos[-1].mark & inf) != pos[-1].mark; + case acc_cond::acc_op::FinNeg: + case acc_cond::acc_op::InfNeg: + SPOT_UNREACHABLE(); + } SPOT_UNREACHABLE(); return false; } @@ -216,39 +216,39 @@ namespace spot inf_eval(acc_cond::mark_t inf, const acc_cond::acc_word* pos) { switch (pos->op) - { - case acc_cond::acc_op::And: - { - auto sub = pos - pos->size; - while (sub < pos) - { - --pos; - if (!inf_eval(inf, pos)) - return false; - pos -= pos->size; - } - return true; - } - case acc_cond::acc_op::Or: - { - auto sub = pos - pos->size; - while (sub < pos) - { - --pos; - if (inf_eval(inf, pos)) - return true; - pos -= pos->size; - } - return false; - } - case acc_cond::acc_op::Inf: - return (pos[-1].mark & inf) == pos[-1].mark; - case acc_cond::acc_op::Fin: - return true; - case acc_cond::acc_op::FinNeg: - case acc_cond::acc_op::InfNeg: - SPOT_UNREACHABLE(); - } + { + case acc_cond::acc_op::And: + { + auto sub = pos - pos->size; + while (sub < pos) + { + --pos; + if (!inf_eval(inf, pos)) + return false; + pos -= pos->size; + } + return true; + } + case acc_cond::acc_op::Or: + { + auto sub = pos - pos->size; + while (sub < pos) + { + --pos; + if (inf_eval(inf, pos)) + return true; + pos -= pos->size; + } + return false; + } + case acc_cond::acc_op::Inf: + return (pos[-1].mark & inf) == pos[-1].mark; + case acc_cond::acc_op::Fin: + return true; + case acc_cond::acc_op::FinNeg: + case acc_cond::acc_op::InfNeg: + SPOT_UNREACHABLE(); + } SPOT_UNREACHABLE(); return false; } @@ -257,44 +257,44 @@ namespace spot eval_sets(acc_cond::mark_t inf, const acc_cond::acc_word* pos) { switch (pos->op) - { - case acc_cond::acc_op::And: - { - auto sub = pos - pos->size; - acc_cond::mark_t m = 0U; - while (sub < pos) - { - --pos; - if (auto s = eval_sets(inf, pos)) - m |= s; - else - return 0U; - pos -= pos->size; - } - return m; - } - case acc_cond::acc_op::Or: - { - auto sub = pos - pos->size; - while (sub < pos) - { - --pos; - if (auto s = eval_sets(inf, pos)) - return s; - pos -= pos->size; - } - return 0U; - } - case acc_cond::acc_op::Inf: - if ((pos[-1].mark & inf) == pos[-1].mark) - return pos[-1].mark; - else - return 0U; - case acc_cond::acc_op::Fin: - case acc_cond::acc_op::FinNeg: - case acc_cond::acc_op::InfNeg: - SPOT_UNREACHABLE(); - } + { + case acc_cond::acc_op::And: + { + auto sub = pos - pos->size; + acc_cond::mark_t m = 0U; + while (sub < pos) + { + --pos; + if (auto s = eval_sets(inf, pos)) + m |= s; + else + return 0U; + pos -= pos->size; + } + return m; + } + case acc_cond::acc_op::Or: + { + auto sub = pos - pos->size; + while (sub < pos) + { + --pos; + if (auto s = eval_sets(inf, pos)) + return s; + pos -= pos->size; + } + return 0U; + } + case acc_cond::acc_op::Inf: + if ((pos[-1].mark & inf) == pos[-1].mark) + return pos[-1].mark; + else + return 0U; + case acc_cond::acc_op::Fin: + case acc_cond::acc_op::FinNeg: + case acc_cond::acc_op::InfNeg: + SPOT_UNREACHABLE(); + } SPOT_UNREACHABLE(); return false; } @@ -318,7 +318,7 @@ namespace spot { if (uses_fin_acceptance()) throw std::runtime_error - ("Fin acceptance is not supported by this code path."); + ("Fin acceptance is not supported by this code path."); if (code_.empty()) return 0U; return eval_sets(inf, &code_.back()); @@ -331,25 +331,25 @@ namespace spot unsigned pos = code_.size(); do { - switch (code_[pos - 1].op) - { - case acc_cond::acc_op::And: - case acc_cond::acc_op::Or: - --pos; - break; - case acc_cond::acc_op::Inf: - case acc_cond::acc_op::InfNeg: - pos -= 2; - break; - case acc_cond::acc_op::Fin: - if (code_[pos - 2].mark == 0U) // f - { - pos -= 2; - break; - } - case acc_cond::acc_op::FinNeg: - return true; - } + switch (code_[pos - 1].op) + { + case acc_cond::acc_op::And: + case acc_cond::acc_op::Or: + --pos; + break; + case acc_cond::acc_op::Inf: + case acc_cond::acc_op::InfNeg: + pos -= 2; + break; + case acc_cond::acc_op::Fin: + if (code_[pos - 2].mark == 0U) // f + { + pos -= 2; + break; + } + case acc_cond::acc_op::FinNeg: + return true; + } } while (pos > 0); return false; @@ -361,56 +361,56 @@ namespace spot // Is Rabin or Streett, depending on highop and lowop. static bool is_rs(const acc_cond::acc_code& code, - acc_cond::acc_op highop, - acc_cond::acc_op lowop, - acc_cond::mark_t all_sets) + acc_cond::acc_op highop, + acc_cond::acc_op lowop, + acc_cond::mark_t all_sets) { unsigned s = code.back().size; auto mainop = code.back().op; if (mainop == highop) - { - // The size must be a multiple of 5. - if ((s != code.size() - 1) || (s % 5)) - return false; - } - else // Single pair? - { - if (s != 4 || mainop != lowop) - return false; - // Pretend we where in a unary highop. - s = 5; - } + { + // The size must be a multiple of 5. + if ((s != code.size() - 1) || (s % 5)) + return false; + } + else // Single pair? + { + if (s != 4 || mainop != lowop) + return false; + // Pretend we where in a unary highop. + s = 5; + } acc_cond::mark_t seen_fin = 0U; acc_cond::mark_t seen_inf = 0U; while (s) - { - if (code[--s].op != lowop) - return false; - auto o1 = code[--s].op; - auto m1 = code[--s].mark; - auto o2 = code[--s].op; - auto m2 = code[--s].mark; + { + if (code[--s].op != lowop) + return false; + auto o1 = code[--s].op; + auto m1 = code[--s].mark; + auto o2 = code[--s].op; + auto m2 = code[--s].mark; - // We assume - // Fin(n) lowop Inf(n+1) - // o1 (m1) o2 (m2) - // swap if it is the converse - if (o2 == acc_cond::acc_op::Fin) - { - std::swap(o1, o2); - std::swap(m1, m2); - } - if (o1 != acc_cond::acc_op::Fin - || o2 != acc_cond::acc_op::Inf - || m1.count() != 1 - || m2.id != (m1.id << 1)) - return false; - seen_fin |= m1; - seen_inf |= m2; - } + // We assume + // Fin(n) lowop Inf(n+1) + // o1 (m1) o2 (m2) + // swap if it is the converse + if (o2 == acc_cond::acc_op::Fin) + { + std::swap(o1, o2); + std::swap(m1, m2); + } + if (o1 != acc_cond::acc_op::Fin + || o2 != acc_cond::acc_op::Inf + || m1.count() != 1 + || m2.id != (m1.id << 1)) + return false; + seen_fin |= m1; + seen_inf |= m2; + } return (!(seen_fin & seen_inf) - && (seen_fin | seen_inf) == all_sets); + && (seen_fin | seen_inf) == all_sets); } } @@ -446,11 +446,11 @@ namespace spot pairs.clear(); if (is_generalized_co_buchi()) { - pairs.resize(num_); - return true; + pairs.resize(num_); + return true; } if (code_.is_t() - || code_.back().op != acc_op::Or) + || code_.back().op != acc_op::Or) return false; auto s = code_.back().size; @@ -461,63 +461,63 @@ namespace spot std::map p; while (s) { - --s; - if (code_[s].op == acc_op::And) - { - auto o1 = code_[--s].op; - auto m1 = code_[--s].mark; - auto o2 = code_[--s].op; - auto m2 = code_[--s].mark; + --s; + if (code_[s].op == acc_op::And) + { + auto o1 = code_[--s].op; + auto m1 = code_[--s].mark; + auto o2 = code_[--s].op; + auto m2 = code_[--s].mark; - // We assume - // Fin(n) & Inf({n+1,n+2,...,n+i}) - // o1 (m1) o2 (m2) - // swap if it is the converse - if (o2 == acc_cond::acc_op::Fin) - { - std::swap(o1, o2); - std::swap(m1, m2); - } + // We assume + // Fin(n) & Inf({n+1,n+2,...,n+i}) + // o1 (m1) o2 (m2) + // swap if it is the converse + if (o2 == acc_cond::acc_op::Fin) + { + std::swap(o1, o2); + std::swap(m1, m2); + } - if (o1 != acc_cond::acc_op::Fin - || o2 != acc_cond::acc_op::Inf - || m1.count() != 1) - return false; + if (o1 != acc_cond::acc_op::Fin + || o2 != acc_cond::acc_op::Inf + || m1.count() != 1) + return false; - unsigned i = m2.count(); - // If we have seen this pair already, it must have the - // same size. - if (p.emplace(m1.max_set(), i).first->second != i) - return false; - assert(i > 0); - unsigned j = m1.max_set(); // == n+1 - do - if (!m2.has(j++)) - return false; - while (--i); + unsigned i = m2.count(); + // If we have seen this pair already, it must have the + // same size. + if (p.emplace(m1.max_set(), i).first->second != i) + return false; + assert(i > 0); + unsigned j = m1.max_set(); // == n+1 + do + if (!m2.has(j++)) + return false; + while (--i); - seen_fin |= m1; - seen_inf |= m2; - } - else if (code_[s].op == acc_op::Fin) - { - auto m1 = code_[--s].mark; - for (auto s: m1.sets()) - // If we have seen this pair already, it must have the - // same size. - if (p.emplace(s, 0U).first->second != 0U) - return false; - seen_fin |= m1; - } - else - { - return false; - } + seen_fin |= m1; + seen_inf |= m2; + } + else if (code_[s].op == acc_op::Fin) + { + auto m1 = code_[--s].mark; + for (auto s: m1.sets()) + // If we have seen this pair already, it must have the + // same size. + if (p.emplace(s, 0U).first->second != 0U) + return false; + seen_fin |= m1; + } + else + { + return false; + } } for (auto i: p) pairs.push_back(i.second); return (!(seen_fin & seen_inf) - && (seen_fin | seen_inf) == all_sets()); + && (seen_fin | seen_inf) == all_sets()); } acc_cond::acc_code @@ -542,10 +542,10 @@ namespace spot int end = max ? sets : -1; for (int i = start; i != end; i += inc) { - if ((i & 1) == odd) - res |= inf({(unsigned)i}); - else - res &= fin({(unsigned)i}); + if ((i & 1) == odd) + res |= inf({(unsigned)i}); + else + res &= fin({(unsigned)i}); } return res; } @@ -564,26 +564,26 @@ namespace spot codes.reserve(n_accs); for (unsigned i = 0; i < n_accs; ++i) { - codes.push_back(drand() < 0.5 ? inf({i}) : fin({i})); - if (reuse > 0.0 && drand() < reuse) - --i; + codes.push_back(drand() < 0.5 ? inf({i}) : fin({i})); + if (reuse > 0.0 && drand() < reuse) + --i; } int s = codes.size(); while (s > 1) { - // Pick a random code and put it at the end - int p1 = mrand(s--); - std::swap(codes[p1], codes[s]); - // and another one - int p2 = mrand(s); + // Pick a random code and put it at the end + int p1 = mrand(s--); + std::swap(codes[p1], codes[s]); + // and another one + int p2 = mrand(s); - if (drand() < 0.5) - codes[p2] |= std::move(codes.back()); - else - codes[p2] &= std::move(codes.back()); + if (drand() < 0.5) + codes[p2] |= std::move(codes.back()); + else + codes[p2] &= std::move(codes.back()); - codes.pop_back(); + codes.pop_back(); } return codes[0]; } @@ -596,57 +596,57 @@ namespace spot auto start = c - sz - 1; auto op = c->op; switch (op) - { - case acc_cond::acc_op::Or: - { - --c; - bdd res = bddfalse; - do - { - res |= to_bdd_rec(c, map); - c -= c->size + 1; - } - while (c > start); - return res; - } - case acc_cond::acc_op::And: - { - --c; - bdd res = bddtrue; - do - { - res &= to_bdd_rec(c, map); - c -= c->size + 1; - } - while (c > start); - return res; - } - case acc_cond::acc_op::Fin: - { - bdd res = bddfalse; - for (auto i: c[-1].mark.sets()) - res |= !map[i]; - return res; - } - case acc_cond::acc_op::Inf: - { - bdd res = bddtrue; - for (auto i: c[-1].mark.sets()) - res &= map[i]; - return res; - } - case acc_cond::acc_op::InfNeg: - case acc_cond::acc_op::FinNeg: - SPOT_UNREACHABLE(); - return bddfalse; - } + { + case acc_cond::acc_op::Or: + { + --c; + bdd res = bddfalse; + do + { + res |= to_bdd_rec(c, map); + c -= c->size + 1; + } + while (c > start); + return res; + } + case acc_cond::acc_op::And: + { + --c; + bdd res = bddtrue; + do + { + res &= to_bdd_rec(c, map); + c -= c->size + 1; + } + while (c > start); + return res; + } + case acc_cond::acc_op::Fin: + { + bdd res = bddfalse; + for (auto i: c[-1].mark.sets()) + res |= !map[i]; + return res; + } + case acc_cond::acc_op::Inf: + { + bdd res = bddtrue; + for (auto i: c[-1].mark.sets()) + res &= map[i]; + return res; + } + case acc_cond::acc_op::InfNeg: + case acc_cond::acc_op::FinNeg: + SPOT_UNREACHABLE(); + return bddfalse; + } SPOT_UNREACHABLE(); return bddfalse; } static bool equiv_codes(const acc_cond::acc_code& lhs, - const acc_cond::acc_code& rhs) + const acc_cond::acc_code& rhs) { auto used = lhs.used_sets() | rhs.used_sets(); @@ -658,10 +658,10 @@ namespace spot assert(base == 0); std::vector r; for (unsigned i = 0; r.size() < umax; ++i) - if (used.has(i)) - r.push_back(bdd_ithvar(base++)); - else - r.push_back(bddfalse); + if (used.has(i)) + r.push_back(bdd_ithvar(base++)); + else + r.push_back(bddfalse); return to_bdd_rec(&lhs.back(), &r[0]) == to_bdd_rec(&rhs.back(), &r[0]); } } @@ -671,9 +671,9 @@ namespace spot unsigned sets = num_; if (sets == 0) { - max = true; - odd = is_t(); - return true; + max = true; + odd = is_t(); + return true; } acc_cond::mark_t u_inf; acc_cond::mark_t u_fin; @@ -682,22 +682,22 @@ namespace spot odd = !u_inf.has(0); for (auto s: u_inf.sets()) if ((s & 1) != odd) - { - max = false; // just so the value is not uninitialized - return false; - } + { + max = false; // just so the value is not uninitialized + return false; + } auto max_code = acc_code::parity(true, odd, sets); if (max_code == code_) { - max = true; - return true; + max = true; + return true; } auto min_code = acc_code::parity(false, odd, sets); if (min_code == code_) { - max = false; - return true; + max = false; + return true; } if (!equiv) @@ -705,13 +705,13 @@ namespace spot if (equiv_codes(code_, max_code)) { - max = true; - return true; + max = true; + return true; } if (equiv_codes(code_, min_code)) { - max = false; - return true; + max = false; + return true; } return false; } @@ -732,15 +732,15 @@ namespace spot std::vector sets(c); for (unsigned i = 0; r.size() < max; ++i) { - if (used.has(i)) - { - sets[base] = i; - r.push_back(bdd_ithvar(base++)); - } - else - { - r.push_back(bddfalse); - } + if (used.has(i)) + { + sets[base] = i; + r.push_back(bdd_ithvar(base++)); + } + else + { + r.push_back(bddfalse); + } } bdd res = to_bdd_rec(&back(), &r[0]); @@ -755,34 +755,34 @@ namespace spot acc_code rescode = f(); while ((cube = isop.next()) != bddfalse) { - mark_t i = 0U; - acc_code c; - while (cube != bddtrue) - { - // The acceptance set associated to this BDD variable - mark_t s = 0U; - s.set(sets[bdd_var(cube)]); + mark_t i = 0U; + acc_code c; + while (cube != bddtrue) + { + // The acceptance set associated to this BDD variable + mark_t s = 0U; + s.set(sets[bdd_var(cube)]); - bdd h = bdd_high(cube); - if (h == bddfalse) // Negative variable? -> Fin - { - cube = bdd_low(cube); - // The strange order here make sure we can smaller set - // numbers at the end of the acceptance code, i.e., at - // the front of the output. - auto a = fin(s) & std::move(c); - std::swap(a, c); - } - else // Positive variable? -> Inf - { - i |= s; - cube = h; - } - } - c &= inf(i); - // See comment above for the order. - c |= std::move(rescode); - std::swap(c, rescode); + bdd h = bdd_high(cube); + if (h == bddfalse) // Negative variable? -> Fin + { + cube = bdd_low(cube); + // The strange order here make sure we can smaller set + // numbers at the end of the acceptance code, i.e., at + // the front of the output. + auto a = fin(s) & std::move(c); + std::swap(a, c); + } + else // Positive variable? -> Inf + { + i |= s; + cube = h; + } + } + c &= inf(i); + // See comment above for the order. + c |= std::move(rescode); + std::swap(c, rescode); } return rescode; @@ -804,15 +804,15 @@ namespace spot std::vector sets(c); for (unsigned i = 0; r.size() < max; ++i) { - if (used.has(i)) - { - sets[base] = i; - r.push_back(bdd_ithvar(base++)); - } - else - { - r.push_back(bddfalse); - } + if (used.has(i)) + { + sets[base] = i; + r.push_back(bdd_ithvar(base++)); + } + else + { + r.push_back(bddfalse); + } } bdd res = to_bdd_rec(&back(), &r[0]); @@ -827,34 +827,34 @@ namespace spot acc_code rescode; while ((cube = isop.next()) != bddfalse) { - mark_t m = 0U; - acc_code c = f(); - while (cube != bddtrue) - { - // The acceptance set associated to this BDD variable - mark_t s = 0U; - s.set(sets[bdd_var(cube)]); + mark_t m = 0U; + acc_code c = f(); + while (cube != bddtrue) + { + // The acceptance set associated to this BDD variable + mark_t s = 0U; + s.set(sets[bdd_var(cube)]); - bdd h = bdd_high(cube); - if (h == bddfalse) // Negative variable? -> Inf - { - cube = bdd_low(cube); - // The strange order here make sure we can smaller set - // numbers at the end of the acceptance code, i.e., at - // the front of the output. - auto a = inf(s) | std::move(c); - std::swap(a, c); - } - else // Positive variable? -> Fin - { - m |= s; - cube = h; - } - } - c |= fin(m); - // See comment above for the order. - c &= std::move(rescode); - std::swap(c, rescode); + bdd h = bdd_high(cube); + if (h == bddfalse) // Negative variable? -> Inf + { + cube = bdd_low(cube); + // The strange order here make sure we can smaller set + // numbers at the end of the acceptance code, i.e., at + // the front of the output. + auto a = inf(s) | std::move(c); + std::swap(a, c); + } + else // Positive variable? -> Fin + { + m |= s; + cube = h; + } + } + c |= fin(m); + // See comment above for the order. + c &= std::move(rescode); + std::swap(c, rescode); } return rescode; } @@ -878,15 +878,15 @@ namespace spot std::vector sets(c); for (unsigned i = 0; r.size() < max; ++i) { - if (used.has(i)) - { - sets[base] = i; - r.push_back(bdd_ithvar(base++)); - } - else - { - r.push_back(bddfalse); - } + if (used.has(i)) + { + sets[base] = i; + r.push_back(bdd_ithvar(base++)); + } + else + { + r.push_back(bddfalse); + } } bdd res = to_bdd_rec(&code_.back(), &r[0]); @@ -900,19 +900,19 @@ namespace spot mark_t i = 0U; while (cube != bddtrue) { - // The acceptance set associated to this BDD variable - int s = sets[bdd_var(cube)]; + // The acceptance set associated to this BDD variable + int s = sets[bdd_var(cube)]; - bdd h = bdd_high(cube); - if (h == bddfalse) // Negative variable? -> skip - { - cube = bdd_low(cube); - } - else // Positive variable? -> Inf - { - i.set(s); - cube = h; - } + bdd h = bdd_high(cube); + if (h == bddfalse) // Negative variable? -> skip + { + cube = bdd_low(cube); + } + else // Positive variable? -> Inf + { + i.set(s); + cube = h; + } } return {true, i}; } @@ -922,12 +922,12 @@ namespace spot { if (empty()) { - if (accepting) - return {}; - else - return { - {} - }; + if (accepting) + return {}; + else + return { + {} + }; } auto used = acc_cond::acc_code::used_sets(); unsigned c = used.count(); @@ -941,18 +941,18 @@ namespace spot bdd known = bddtrue; for (unsigned i = 0; r.size() < max; ++i) { - if (used.has(i)) - { - sets[base] = i; - bdd v = bdd_ithvar(base++); - r.push_back(v); - if (inf.has(i)) - known &= v; - } - else - { - r.push_back(bddfalse); - } + if (used.has(i)) + { + sets[base] = i; + bdd v = bdd_ithvar(base++); + r.push_back(v); + if (inf.has(i)) + known &= v; + } + else + { + r.push_back(bddfalse); + } } bdd res = to_bdd_rec(&back(), &r[0]); @@ -970,25 +970,25 @@ namespace spot std::vector> result; while ((cube = isop.next()) != bddfalse) { - std::vector partial; - while (cube != bddtrue) - { - // The acceptance set associated to this BDD variable - int s = sets[bdd_var(cube)]; + std::vector partial; + while (cube != bddtrue) + { + // The acceptance set associated to this BDD variable + int s = sets[bdd_var(cube)]; - bdd h = bdd_high(cube); - if (h == bddfalse) // Negative variable - { - partial.push_back(s); - cube = bdd_low(cube); - } - else // Positive variable - { - partial.push_back(-s - 1); - cube = h; - } - } - result.emplace_back(std::move(partial)); + bdd h = bdd_high(cube); + if (h == bddfalse) // Negative variable + { + partial.push_back(s); + cube = bdd_low(cube); + } + else // Positive variable + { + partial.push_back(-s - 1); + cube = h; + } + } + result.emplace_back(std::move(partial)); } return result; } @@ -1004,24 +1004,24 @@ namespace spot --pos; while (pos > start) { - switch (pos->op) - { - case acc_cond::acc_op::Or: - return false; - case acc_cond::acc_op::And: - and_scope = std::min(and_scope, pos - pos->size); - --pos; - break; - case acc_cond::acc_op::Fin: - case acc_cond::acc_op::FinNeg: - if (pos[-1].mark.count() > 1 && pos > and_scope) - return false; - /* fall through */ - case acc_cond::acc_op::Inf: - case acc_cond::acc_op::InfNeg: - pos -= 2; - break; - } + switch (pos->op) + { + case acc_cond::acc_op::Or: + return false; + case acc_cond::acc_op::And: + and_scope = std::min(and_scope, pos - pos->size); + --pos; + break; + case acc_cond::acc_op::Fin: + case acc_cond::acc_op::FinNeg: + if (pos[-1].mark.count() > 1 && pos > and_scope) + return false; + /* fall through */ + case acc_cond::acc_op::Inf: + case acc_cond::acc_op::InfNeg: + pos -= 2; + break; + } } return true; } @@ -1037,24 +1037,24 @@ namespace spot --pos; while (pos > start) { - switch (pos->op) - { - case acc_cond::acc_op::And: - return false; - case acc_cond::acc_op::Or: - or_scope = std::min(or_scope, pos - pos->size); - --pos; - break; - case acc_cond::acc_op::Inf: - case acc_cond::acc_op::InfNeg: - if (pos[-1].mark.count() > 1 && pos > or_scope) - return false; - /* fall through */ - case acc_cond::acc_op::Fin: - case acc_cond::acc_op::FinNeg: - pos -= 2; - break; - } + switch (pos->op) + { + case acc_cond::acc_op::And: + return false; + case acc_cond::acc_op::Or: + or_scope = std::min(or_scope, pos - pos->size); + --pos; + break; + case acc_cond::acc_op::Inf: + case acc_cond::acc_op::InfNeg: + if (pos[-1].mark.count() > 1 && pos > or_scope) + return false; + /* fall through */ + case acc_cond::acc_op::Fin: + case acc_cond::acc_op::FinNeg: + pos -= 2; + break; + } } return true; } @@ -1065,42 +1065,42 @@ namespace spot { auto start = pos - pos->size; switch (pos->op) - { - case acc_cond::acc_op::And: - { - --pos; - auto res = acc_cond::acc_code::f(); - do - { - auto tmp = complement_rec(pos) | std::move(res); - std::swap(tmp, res); - pos -= pos->size + 1; - } - while (pos > start); - return res; - } - case acc_cond::acc_op::Or: - { - --pos; - auto res = acc_cond::acc_code::t(); - do - { - auto tmp = complement_rec(pos) & std::move(res); - std::swap(tmp, res); - pos -= pos->size + 1; - } - while (pos > start); - return res; - } - case acc_cond::acc_op::Fin: - return acc_cond::acc_code::inf(pos[-1].mark); - case acc_cond::acc_op::Inf: - return acc_cond::acc_code::fin(pos[-1].mark); - case acc_cond::acc_op::FinNeg: - return acc_cond::acc_code::inf_neg(pos[-1].mark); - case acc_cond::acc_op::InfNeg: - return acc_cond::acc_code::fin_neg(pos[-1].mark); - } + { + case acc_cond::acc_op::And: + { + --pos; + auto res = acc_cond::acc_code::f(); + do + { + auto tmp = complement_rec(pos) | std::move(res); + std::swap(tmp, res); + pos -= pos->size + 1; + } + while (pos > start); + return res; + } + case acc_cond::acc_op::Or: + { + --pos; + auto res = acc_cond::acc_code::t(); + do + { + auto tmp = complement_rec(pos) & std::move(res); + std::swap(tmp, res); + pos -= pos->size + 1; + } + while (pos > start); + return res; + } + case acc_cond::acc_op::Fin: + return acc_cond::acc_code::inf(pos[-1].mark); + case acc_cond::acc_op::Inf: + return acc_cond::acc_code::fin(pos[-1].mark); + case acc_cond::acc_op::FinNeg: + return acc_cond::acc_code::inf_neg(pos[-1].mark); + case acc_cond::acc_op::InfNeg: + return acc_cond::acc_code::fin_neg(pos[-1].mark); + } SPOT_UNREACHABLE(); return {}; } @@ -1122,46 +1122,46 @@ namespace spot { auto start = pos - pos->size; switch (pos->op) - { - case acc_cond::acc_op::And: - { - --pos; - auto res = acc_cond::acc_code::t(); - do - { - auto tmp = strip_rec(pos, rem, missing) & std::move(res); - std::swap(tmp, res); - pos -= pos->size + 1; - } - while (pos > start); - return res; - } - case acc_cond::acc_op::Or: - { - --pos; - auto res = acc_cond::acc_code::f(); - do - { - auto tmp = strip_rec(pos, rem, missing) | std::move(res); - std::swap(tmp, res); - pos -= pos->size + 1; - } - while (pos > start); - return res; - } - case acc_cond::acc_op::Fin: - if (missing && (pos[-1].mark & rem)) - return acc_cond::acc_code::t(); - return acc_cond::acc_code::fin(pos[-1].mark.strip(rem)); - case acc_cond::acc_op::Inf: - if (missing && (pos[-1].mark & rem)) - return acc_cond::acc_code::f(); - return acc_cond::acc_code::inf(pos[-1].mark.strip(rem)); - case acc_cond::acc_op::FinNeg: - case acc_cond::acc_op::InfNeg: - SPOT_UNREACHABLE(); - return {}; - } + { + case acc_cond::acc_op::And: + { + --pos; + auto res = acc_cond::acc_code::t(); + do + { + auto tmp = strip_rec(pos, rem, missing) & std::move(res); + std::swap(tmp, res); + pos -= pos->size + 1; + } + while (pos > start); + return res; + } + case acc_cond::acc_op::Or: + { + --pos; + auto res = acc_cond::acc_code::f(); + do + { + auto tmp = strip_rec(pos, rem, missing) | std::move(res); + std::swap(tmp, res); + pos -= pos->size + 1; + } + while (pos > start); + return res; + } + case acc_cond::acc_op::Fin: + if (missing && (pos[-1].mark & rem)) + return acc_cond::acc_code::t(); + return acc_cond::acc_code::fin(pos[-1].mark.strip(rem)); + case acc_cond::acc_op::Inf: + if (missing && (pos[-1].mark & rem)) + return acc_cond::acc_code::f(); + return acc_cond::acc_code::inf(pos[-1].mark.strip(rem)); + case acc_cond::acc_op::FinNeg: + case acc_cond::acc_op::InfNeg: + SPOT_UNREACHABLE(); + return {}; + } SPOT_UNREACHABLE(); return {}; } @@ -1185,20 +1185,20 @@ namespace spot auto end = &front(); while (pos > end) { - switch (pos->op) - { - case acc_cond::acc_op::And: - case acc_cond::acc_op::Or: - --pos; - break; - case acc_cond::acc_op::Fin: - case acc_cond::acc_op::Inf: - case acc_cond::acc_op::FinNeg: - case acc_cond::acc_op::InfNeg: - used_in_cond |= pos[-1].mark; - pos -= 2; - break; - } + switch (pos->op) + { + case acc_cond::acc_op::And: + case acc_cond::acc_op::Or: + --pos; + break; + case acc_cond::acc_op::Fin: + case acc_cond::acc_op::Inf: + case acc_cond::acc_op::FinNeg: + case acc_cond::acc_op::InfNeg: + used_in_cond |= pos[-1].mark; + pos -= 2; + break; + } } return used_in_cond; } @@ -1215,56 +1215,56 @@ namespace spot auto end = &front(); while (pos > end) { - switch (pos->op) - { - case acc_cond::acc_op::And: - case acc_cond::acc_op::Or: - --pos; - break; - case acc_cond::acc_op::Fin: - case acc_cond::acc_op::FinNeg: - used_fin |= pos[-1].mark; - pos -= 2; - break; - case acc_cond::acc_op::Inf: - case acc_cond::acc_op::InfNeg: - used_inf |= pos[-1].mark; - pos -= 2; - break; - } + switch (pos->op) + { + case acc_cond::acc_op::And: + case acc_cond::acc_op::Or: + --pos; + break; + case acc_cond::acc_op::Fin: + case acc_cond::acc_op::FinNeg: + used_fin |= pos[-1].mark; + pos -= 2; + break; + case acc_cond::acc_op::Inf: + case acc_cond::acc_op::InfNeg: + used_inf |= pos[-1].mark; + pos -= 2; + break; + } } return {used_inf, used_fin}; } std::ostream& acc_cond::acc_code::to_html(std::ostream& os, - std::function - set_printer) const + std::function + set_printer) const { if (empty()) os << 't'; else print_code(os, *this, size() - 1, - set_printer ? set_printer : default_set_printer); + set_printer ? set_printer : default_set_printer); return os; } std::ostream& acc_cond::acc_code::to_text(std::ostream& os, - std::function - set_printer) const + std::function + set_printer) const { if (empty()) os << 't'; else print_code(os, *this, size() - 1, - set_printer ? set_printer : default_set_printer); + set_printer ? set_printer : default_set_printer); return os; } std::ostream& operator<<(std::ostream& os, - const spot::acc_cond::acc_code& code) + const spot::acc_cond::acc_code& code) { return code.to_text(os); } @@ -1280,9 +1280,9 @@ namespace spot std::ostringstream s; s << "syntax error at "; if (*input) - s << '\'' << input << "': "; + s << '\'' << input << "': "; else - s << "end of acceptance: "; + s << "end of acceptance: "; s << message; throw parse_error(s.str()); } @@ -1295,7 +1295,7 @@ namespace spot static void skip_space(const char*& input) { while (std::isspace(*input)) - ++input; + ++input; } // Eat c and remove the following spaces. @@ -1303,11 +1303,11 @@ namespace spot void expect(const char*& input, char c) { if (*input != c) - { - char msg[20]; - sprintf(msg, "was expecting %c '.'", c); - syntax_error(input, msg); - } + { + char msg[20]; + sprintf(msg, "was expecting %c '.'", c); + syntax_error(input, msg); + } ++input; skip_space(input); } @@ -1319,14 +1319,14 @@ namespace spot auto res = parse_term(input); skip_space(input); while (*input == '|') - { - ++input; - skip_space(input); - // Prepend instead of append, to preserve the input order. - auto tmp = parse_term(input); - std::swap(tmp, res); - res |= std::move(tmp); - } + { + ++input; + skip_space(input); + // Prepend instead of append, to preserve the input order. + auto tmp = parse_term(input); + std::swap(tmp, res); + res |= std::move(tmp); + } return res; } @@ -1338,7 +1338,7 @@ namespace spot unsigned long n = strtoul(input, &end, 10); unsigned num = n; if (errno || num != n) - syntax_error(input, "invalid number."); + syntax_error(input, "invalid number."); input = end; return n; } @@ -1352,43 +1352,43 @@ namespace spot errno = 0; min = strtol(str, &end, 10); if (end == str || errno) - { - // No leading number. It's OK as long as '..' or ':' are next. - if (errno || (*end != ':' && *end != '.')) - syntax_error(str, "invalid range."); - min = 1; - } + { + // No leading number. It's OK as long as '..' or ':' are next. + if (errno || (*end != ':' && *end != '.')) + syntax_error(str, "invalid range."); + min = 1; + } if (!*end || (*end != ':' && *end != '.')) - { - // Only one number. - max = min; - } + { + // Only one number. + max = min; + } else - { - // Skip : or .. - if (end[0] == ':') - ++end; - else if (end[0] == '.' && end[1] == '.') - end += 2; + { + // Skip : or .. + if (end[0] == ':') + ++end; + else if (end[0] == '.' && end[1] == '.') + end += 2; - // Parse the next integer. - char* end2; - max = strtol(end, &end2, 10); - if (end == end2 || errno) - syntax_error(str, "invalid range (missing end?)"); - end = end2; - } + // Parse the next integer. + char* end2; + max = strtol(end, &end2, 10); + if (end == end2 || errno) + syntax_error(str, "invalid range (missing end?)"); + end = end2; + } if (min < 0 || max < 0) - syntax_error(str, "values in range must be positive."); + syntax_error(str, "values in range must be positive."); str = end; if (min == max) - return min; + return min; if (min > max) - std::swap(min, max); + std::swap(min, max); return spot::rrand(min, max); } @@ -1408,9 +1408,9 @@ namespace spot char* end; double n = strtod(input, &end); if (errno) - syntax_error(input, "cannot convert to double."); + syntax_error(input, "cannot convert to double."); if (!(n >= 0.0 && n <= 1.0)) - syntax_error(input, "value should be between 0 and 1."); + syntax_error(input, "value should be between 0 and 1."); input = end; return n; } @@ -1419,48 +1419,48 @@ namespace spot { acc_cond::acc_code res; if (*input == 't') - { - ++input; - res = acc_cond::acc_code::t(); - } + { + ++input; + res = acc_cond::acc_code::t(); + } else if (*input == 'f') - { - ++input; - res = acc_cond::acc_code::f(); - } + { + ++input; + res = acc_cond::acc_code::f(); + } else if (*input == '(') - { - ++input; - skip_space(input); - res = parse_acc(input); - skip_space(input); - expect(input, ')'); - } + { + ++input; + skip_space(input); + res = parse_acc(input); + skip_space(input); + expect(input, ')'); + } else if (!strncmp(input, "Inf", 3)) - { - input += 3; - res = acc_cond::acc_code::inf({parse_par_num(input)}); - } + { + input += 3; + res = acc_cond::acc_code::inf({parse_par_num(input)}); + } else if (!strncmp(input, "Fin", 3)) - { - input += 3; - res = acc_cond::acc_code::fin({parse_par_num(input)}); - } + { + input += 3; + res = acc_cond::acc_code::fin({parse_par_num(input)}); + } else - { - syntax_error(input, "unexpected character."); - } + { + syntax_error(input, "unexpected character."); + } skip_space(input); while (*input == '&') - { - ++input; - skip_space(input); - // Prepend instead of append, to preserve the input order. - auto tmp = parse_term(input); - std::swap(tmp, res); - res &= std::move(tmp); - } + { + ++input; + skip_space(input); + // Prepend instead of append, to preserve the input order. + auto tmp = parse_term(input); + std::swap(tmp, res); + res &= std::move(tmp); + } return res; } @@ -1468,25 +1468,25 @@ namespace spot { skip_space(input); if (!strncmp(input, "max", 3)) - { - input += 3; - return true; - } + { + input += 3; + return true; + } if (!strncmp(input, "min", 3)) - { - input += 3; - return false; - } + { + input += 3; + return false; + } if (!strncmp(input, "rand", 4)) - { - input += 4; - return drand() < 0.5; - } + { + input += 4; + return drand() < 0.5; + } if (!strncmp(input, "random", 6)) - { - input += 6; - return drand() < 0.5; - } + { + input += 6; + return drand() < 0.5; + } syntax_error(input, "expecting 'min', 'max', or 'rand'."); SPOT_UNREACHABLE(); return false; @@ -1496,25 +1496,25 @@ namespace spot { skip_space(input); if (!strncmp(input, "odd", 3)) - { - input += 3; - return true; - } + { + input += 3; + return true; + } if (!strncmp(input, "even", 4)) - { - input += 4; - return false; - } + { + input += 4; + return false; + } if (!strncmp(input, "rand", 4)) - { - input += 4; - return drand() < 0.5; - } + { + input += 4; + return drand() < 0.5; + } if (!strncmp(input, "random", 6)) - { - input += 6; - return drand() < 0.5; - } + { + input += 6; + return drand() < 0.5; + } syntax_error(input, "expecting 'odd', 'even', or 'rand'."); SPOT_UNREACHABLE(); return false; @@ -1528,79 +1528,79 @@ namespace spot acc_cond::acc_code c; if (!strncmp(input, "all", 3)) { - input += 3; - c = acc_cond::acc_code::t(); + input += 3; + c = acc_cond::acc_code::t(); } else if (!strncmp(input, "none", 4)) { - input += 4; - c = acc_cond::acc_code::f(); + input += 4; + c = acc_cond::acc_code::f(); } else if (!strncmp(input, "Buchi", 5)) { - input += 5; - c = acc_cond::acc_code::buchi(); + input += 5; + c = acc_cond::acc_code::buchi(); } else if (!strncmp(input, "co-Buchi", 8)) { - input += 8; - c = acc_cond::acc_code::cobuchi(); + input += 8; + c = acc_cond::acc_code::cobuchi(); } else if (!strncmp(input, "generalized-Buchi", 17)) { - input += 17; - c = acc_cond::acc_code::generalized_buchi(parse_range(input)); + input += 17; + c = acc_cond::acc_code::generalized_buchi(parse_range(input)); } else if (!strncmp(input, "generalized-co-Buchi", 20)) { - input += 20; - c = acc_cond::acc_code::generalized_co_buchi(parse_range(input)); + input += 20; + c = acc_cond::acc_code::generalized_co_buchi(parse_range(input)); } else if (!strncmp(input, "Rabin", 5)) { - input += 5; - c = acc_cond::acc_code::rabin(parse_range(input)); + input += 5; + c = acc_cond::acc_code::rabin(parse_range(input)); } else if (!strncmp(input, "Streett", 7)) { - input += 7; - c = acc_cond::acc_code::streett(parse_range(input)); + input += 7; + c = acc_cond::acc_code::streett(parse_range(input)); } else if (!strncmp(input, "generalized-Rabin", 17)) { - input += 17; - unsigned num = parse_num(input); - std::vector v; - v.reserve(num); - while (num > 0) - { - v.push_back(parse_range(input)); - --num; - } - c = acc_cond::acc_code::generalized_rabin(v.begin(), v.end()); + input += 17; + unsigned num = parse_num(input); + std::vector v; + v.reserve(num); + while (num > 0) + { + v.push_back(parse_range(input)); + --num; + } + c = acc_cond::acc_code::generalized_rabin(v.begin(), v.end()); } else if (!strncmp(input, "parity", 6)) { - input += 6; - bool max = max_or_min(input); - bool odd = odd_or_even(input); - unsigned num = parse_range(input); - c = acc_cond::acc_code::parity(max, odd, num); + input += 6; + bool max = max_or_min(input); + bool odd = odd_or_even(input); + unsigned num = parse_range(input); + c = acc_cond::acc_code::parity(max, odd, num); } else if (!strncmp(input, "random", 6)) { - input += 6; - unsigned n = parse_range(input); - skip_space(input); - auto setreuse = input; - double reuse = (*input) ? parse_proba(input) : 0.0; - if (reuse >= 1.0) - syntax_error(setreuse, "probability for set reuse should be <1."); - c = acc_cond::acc_code::random(n, reuse); + input += 6; + unsigned n = parse_range(input); + skip_space(input); + auto setreuse = input; + double reuse = (*input) ? parse_proba(input) : 0.0; + if (reuse >= 1.0) + syntax_error(setreuse, "probability for set reuse should be <1."); + c = acc_cond::acc_code::random(n, reuse); } else { - c = parse_acc(input); + c = parse_acc(input); } skip_space(input); if (*input) diff --git a/spot/twa/acc.hh b/spot/twa/acc.hh index 38add6566..b18f167f4 100644 --- a/spot/twa/acc.hh +++ b/spot/twa/acc.hh @@ -39,193 +39,193 @@ namespace spot mark_t() = default; mark_t(value_t id) noexcept - : id(id) + : id(id) { } template mark_t(const iterator& begin, const iterator& end) noexcept { - id = 0U; - for (iterator i = begin; i != end; ++i) - set(*i); + id = 0U; + for (iterator i = begin; i != end; ++i) + set(*i); } mark_t(std::initializer_list vals) noexcept - : mark_t(vals.begin(), vals.end()) + : mark_t(vals.begin(), vals.end()) { } bool operator==(unsigned o) const { - assert(o == 0U); - return id == o; + assert(o == 0U); + return id == o; } bool operator!=(unsigned o) const { - assert(o == 0U); - return id != o; + assert(o == 0U); + return id != o; } bool operator==(mark_t o) const { - return id == o.id; + return id == o.id; } bool operator!=(mark_t o) const { - return id != o.id; + return id != o.id; } bool operator<(mark_t o) const { - return id < o.id; + return id < o.id; } bool operator<=(mark_t o) const { - return id <= o.id; + return id <= o.id; } bool operator>(mark_t o) const { - return id > o.id; + return id > o.id; } bool operator>=(mark_t o) const { - return id >= o.id; + return id >= o.id; } operator bool() const { - return id != 0; + return id != 0; } bool has(unsigned u) const { - return id & (1U << u); + return id & (1U << u); } void set(unsigned u) { - id |= (1U << u); + id |= (1U << u); } void clear(unsigned u) { - id &= ~(1U << u); + id &= ~(1U << u); } mark_t& operator&=(mark_t r) { - id &= r.id; - return *this; + id &= r.id; + return *this; } mark_t& operator|=(mark_t r) { - id |= r.id; - return *this; + id |= r.id; + return *this; } mark_t& operator-=(mark_t r) { - id &= ~r.id; - return *this; + id &= ~r.id; + return *this; } mark_t& operator^=(mark_t r) { - id ^= r.id; - return *this; + id ^= r.id; + return *this; } mark_t operator&(mark_t r) const { - return id & r.id; + return id & r.id; } mark_t operator|(mark_t r) const { - return id | r.id; + return id | r.id; } mark_t operator-(mark_t r) const { - return id & ~r.id; + return id & ~r.id; } mark_t operator~() const { - return ~id; + return ~id; } mark_t operator^(mark_t r) const { - return id ^ r.id; + return id ^ r.id; } mark_t operator<<(unsigned i) const { - return id << i; + return id << i; } mark_t& operator<<=(unsigned i) { - id <<= i; - return *this; + id <<= i; + return *this; } mark_t operator>>(unsigned i) const { - return id >> i; + return id >> i; } mark_t& operator>>=(unsigned i) { - id >>= i; - return *this; + id >>= i; + return *this; } mark_t strip(mark_t y) const { - // strip every bit of id that is marked in y - // 100101110100.strip( - // 001011001000) - // == 10 1 11 100 - // == 10111100 + // strip every bit of id that is marked in y + // 100101110100.strip( + // 001011001000) + // == 10 1 11 100 + // == 10111100 - auto xv = id; // 100101110100 - auto yv = y.id; // 001011001000 + auto xv = id; // 100101110100 + auto yv = y.id; // 001011001000 - while (yv && xv) - { - // Mask for everything after the last 1 in y - auto rm = (~yv) & (yv - 1); // 000000000111 - // Mask for everything before the last 1 in y - auto lm = ~(yv ^ (yv - 1)); // 111111110000 - xv = ((xv & lm) >> 1) | (xv & rm); - yv = (yv & lm) >> 1; - } - return xv; + while (yv && xv) + { + // Mask for everything after the last 1 in y + auto rm = (~yv) & (yv - 1); // 000000000111 + // Mask for everything before the last 1 in y + auto lm = ~(yv ^ (yv - 1)); // 111111110000 + xv = ((xv & lm) >> 1) | (xv & rm); + yv = (yv & lm) >> 1; + } + return xv; } // Number of bits sets. unsigned count() const { #ifdef __GNUC__ - return __builtin_popcount(id); + return __builtin_popcount(id); #else - unsigned c = 0U; - auto v = id; - while (v) - { - ++c; - v &= v - 1; - } - return c; + unsigned c = 0U; + auto v = id; + while (v) + { + ++c; + v &= v - 1; + } + return c; #endif } @@ -234,50 +234,50 @@ namespace spot // but if the sets {1,3,8} are used, this returns 9. unsigned max_set() const { - auto i = id; - int res = 0; - while (i) - { - ++res; - i >>= 1; - } - return res; + auto i = id; + int res = 0; + while (i) + { + ++res; + i >>= 1; + } + return res; } // Return the lowest acceptance mark mark_t lowest() const { - return id & -id; + return id & -id; } // Remove n bits that where set mark_t& remove_some(unsigned n) { - while (n--) - id &= id - 1; - return *this; + while (n--) + id &= id - 1; + return *this; } template void fill(iterator here) const { - auto a = id; - unsigned level = 0; - while (a) - { - if (a & 1) - *here++ = level; - ++level; - a >>= 1; - } + auto a = id; + unsigned level = 0; + while (a) + { + if (a & 1) + *here++ = level; + ++level; + a >>= 1; + } } // FIXME: Return some iterable object without building a vector. std::vector sets() const { - std::vector res; - fill(std::back_inserter(res)); - return res; + std::vector res; + fill(std::back_inserter(res)); + return res; } SPOT_API @@ -291,9 +291,9 @@ namespace spot { mark_t mark; struct { - acc_op op; // Operator - unsigned short size; // Size of the subtree (number of acc_word), - // not counting this node. + acc_op op; // Operator + unsigned short size; // Size of the subtree (number of acc_word), + // not counting this node. }; }; @@ -301,255 +301,255 @@ namespace spot { bool operator==(const acc_code& other) const { - unsigned pos = size(); - if (other.size() != pos) - return false; - while (pos > 0) - { - auto op = (*this)[pos - 1].op; - auto sz = (*this)[pos - 1].size; - if (other[pos - 1].op != op || - other[pos - 1].size != sz) - return false; - switch (op) - { - case acc_cond::acc_op::And: - case acc_cond::acc_op::Or: - --pos; - break; - case acc_cond::acc_op::Inf: - case acc_cond::acc_op::InfNeg: - case acc_cond::acc_op::Fin: - case acc_cond::acc_op::FinNeg: - pos -= 2; - if (other[pos].mark != (*this)[pos].mark) - return false; - break; - } - } - return true; + unsigned pos = size(); + if (other.size() != pos) + return false; + while (pos > 0) + { + auto op = (*this)[pos - 1].op; + auto sz = (*this)[pos - 1].size; + if (other[pos - 1].op != op || + other[pos - 1].size != sz) + return false; + switch (op) + { + case acc_cond::acc_op::And: + case acc_cond::acc_op::Or: + --pos; + break; + case acc_cond::acc_op::Inf: + case acc_cond::acc_op::InfNeg: + case acc_cond::acc_op::Fin: + case acc_cond::acc_op::FinNeg: + pos -= 2; + if (other[pos].mark != (*this)[pos].mark) + return false; + break; + } + } + return true; }; bool operator<(const acc_code& other) const { - unsigned pos = size(); - auto osize = other.size(); - if (pos < osize) - return true; - if (pos > osize) - return false; - while (pos > 0) - { - auto op = (*this)[pos - 1].op; - auto oop = other[pos - 1].op; - if (op < oop) - return true; - if (op > oop) - return false; - auto sz = (*this)[pos - 1].size; - auto osz = other[pos - 1].size; - if (sz < osz) - return true; - if (sz > osz) - return false; - switch (op) - { - case acc_cond::acc_op::And: - case acc_cond::acc_op::Or: - --pos; - break; - case acc_cond::acc_op::Inf: - case acc_cond::acc_op::InfNeg: - case acc_cond::acc_op::Fin: - case acc_cond::acc_op::FinNeg: - pos -= 2; - auto m = (*this)[pos].mark; - auto om = other[pos].mark; - if (m < om) - return true; - if (m > om) - return false; - break; - } - } - return false; + unsigned pos = size(); + auto osize = other.size(); + if (pos < osize) + return true; + if (pos > osize) + return false; + while (pos > 0) + { + auto op = (*this)[pos - 1].op; + auto oop = other[pos - 1].op; + if (op < oop) + return true; + if (op > oop) + return false; + auto sz = (*this)[pos - 1].size; + auto osz = other[pos - 1].size; + if (sz < osz) + return true; + if (sz > osz) + return false; + switch (op) + { + case acc_cond::acc_op::And: + case acc_cond::acc_op::Or: + --pos; + break; + case acc_cond::acc_op::Inf: + case acc_cond::acc_op::InfNeg: + case acc_cond::acc_op::Fin: + case acc_cond::acc_op::FinNeg: + pos -= 2; + auto m = (*this)[pos].mark; + auto om = other[pos].mark; + if (m < om) + return true; + if (m > om) + return false; + break; + } + } + return false; } bool operator>(const acc_code& other) const { - return other < *this; + return other < *this; } bool operator<=(const acc_code& other) const { - return !(other < *this); + return !(other < *this); } bool operator>=(const acc_code& other) const { - return !(*this < other); + return !(*this < other); } bool operator!=(const acc_code& other) const { - return !(*this == other); + return !(*this == other); } bool is_t() const { - unsigned s = size(); - return s == 0 - || ((*this)[s - 1].op == acc_op::Inf && (*this)[s - 2].mark == 0U); + unsigned s = size(); + return s == 0 + || ((*this)[s - 1].op == acc_op::Inf && (*this)[s - 2].mark == 0U); } bool is_f() const { - unsigned s = size(); - return s > 1 - && (*this)[s - 1].op == acc_op::Fin && (*this)[s - 2].mark == 0U; + unsigned s = size(); + return s > 1 + && (*this)[s - 1].op == acc_op::Fin && (*this)[s - 2].mark == 0U; } static acc_code f() { - acc_code res; - res.resize(2); - res[0].mark = 0U; - res[1].op = acc_op::Fin; - res[1].size = 1; - return res; + acc_code res; + res.resize(2); + res[0].mark = 0U; + res[1].op = acc_op::Fin; + res[1].size = 1; + return res; } static acc_code t() { - return {}; + return {}; } static acc_code fin(mark_t m) { - acc_code res; - res.resize(2); - res[0].mark = m; - res[1].op = acc_op::Fin; - res[1].size = 1; - return res; + acc_code res; + res.resize(2); + res[0].mark = m; + res[1].op = acc_op::Fin; + res[1].size = 1; + return res; } static acc_code fin(std::initializer_list vals) { - return fin(mark_t(vals)); + return fin(mark_t(vals)); } static acc_code fin_neg(mark_t m) { - acc_code res; - res.resize(2); - res[0].mark = m; - res[1].op = acc_op::FinNeg; - res[1].size = 1; - return res; + acc_code res; + res.resize(2); + res[0].mark = m; + res[1].op = acc_op::FinNeg; + res[1].size = 1; + return res; } static acc_code fin_neg(std::initializer_list vals) { - return fin_neg(mark_t(vals)); + return fin_neg(mark_t(vals)); } static acc_code inf(mark_t m) { - acc_code res; - res.resize(2); - res[0].mark = m; - res[1].op = acc_op::Inf; - res[1].size = 1; - return res; + acc_code res; + res.resize(2); + res[0].mark = m; + res[1].op = acc_op::Inf; + res[1].size = 1; + return res; } static acc_code inf(std::initializer_list vals) { - return inf(mark_t(vals)); + return inf(mark_t(vals)); } static acc_code inf_neg(mark_t m) { - acc_code res; - res.resize(2); - res[0].mark = m; - res[1].op = acc_op::InfNeg; - res[1].size = 1; - return res; + acc_code res; + res.resize(2); + res[0].mark = m; + res[1].op = acc_op::InfNeg; + res[1].size = 1; + return res; } static acc_code inf_neg(std::initializer_list vals) { - return inf_neg(mark_t(vals)); + return inf_neg(mark_t(vals)); } static acc_code buchi() { - return inf({0}); + return inf({0}); } static acc_code cobuchi() { - return fin({0}); + return fin({0}); } static acc_code generalized_buchi(unsigned n) { - acc_cond::mark_t m = (1U << n) - 1; - if (n == 8 * sizeof(mark_t::value_t)) - m = mark_t(-1U); - return inf(m); + acc_cond::mark_t m = (1U << n) - 1; + if (n == 8 * sizeof(mark_t::value_t)) + m = mark_t(-1U); + return inf(m); } static acc_code generalized_co_buchi(unsigned n) { - acc_cond::mark_t m = (1U << n) - 1; - if (n == 8 * sizeof(mark_t::value_t)) - m = mark_t(-1U); - return fin(m); + acc_cond::mark_t m = (1U << n) - 1; + if (n == 8 * sizeof(mark_t::value_t)) + m = mark_t(-1U); + return fin(m); } // n is a number of pairs. static acc_code rabin(unsigned n) { - acc_cond::acc_code res = f(); - while (n > 0) - { - res |= inf({2*n - 1}) & fin({2*n - 2}); - --n; - } - return res; + acc_cond::acc_code res = f(); + while (n > 0) + { + res |= inf({2*n - 1}) & fin({2*n - 2}); + --n; + } + return res; } // n is a number of pairs. static acc_code streett(unsigned n) { - acc_cond::acc_code res = t(); - while (n > 0) - { - res &= inf({2*n - 1}) | fin({2*n - 2}); - --n; - } - return res; + acc_cond::acc_code res = t(); + while (n > 0) + { + res &= inf({2*n - 1}) | fin({2*n - 2}); + --n; + } + return res; } template static acc_code generalized_rabin(Iterator begin, Iterator end) { - acc_cond::acc_code res = f(); - unsigned n = 0; - for (Iterator i = begin; i != end; ++i) - { - acc_cond::acc_code pair = fin({n++}); - acc_cond::mark_t m = 0U; - for (unsigned ni = *i; ni > 0; --ni) - m.set(n++); - pair &= inf(m); - std::swap(pair, res); - res |= std::move(pair); - } - return res; + acc_cond::acc_code res = f(); + unsigned n = 0; + for (Iterator i = begin; i != end; ++i) + { + acc_cond::acc_code pair = fin({n++}); + acc_cond::mark_t m = 0U; + for (unsigned ni = *i; ni > 0; --ni) + m.set(n++); + pair &= inf(m); + std::swap(pair, res); + res |= std::move(pair); + } + return res; } static acc_code parity(bool max, bool odd, unsigned sets); @@ -561,281 +561,281 @@ namespace spot acc_code& operator&=(acc_code&& r) { - if (is_t() || r.is_f()) - { - *this = std::move(r); - return *this; - } - if (is_f() || r.is_t()) - return *this; - unsigned s = size() - 1; - unsigned rs = r.size() - 1; - // We want to group all Inf(x) operators: - // Inf(a) & Inf(b) = Inf(a & b) - if (((*this)[s].op == acc_op::Inf && r[rs].op == acc_op::Inf) - || ((*this)[s].op == acc_op::InfNeg && r[rs].op == acc_op::InfNeg)) - { - (*this)[s - 1].mark |= r[rs - 1].mark; - return *this; - } + if (is_t() || r.is_f()) + { + *this = std::move(r); + return *this; + } + if (is_f() || r.is_t()) + return *this; + unsigned s = size() - 1; + unsigned rs = r.size() - 1; + // We want to group all Inf(x) operators: + // Inf(a) & Inf(b) = Inf(a & b) + if (((*this)[s].op == acc_op::Inf && r[rs].op == acc_op::Inf) + || ((*this)[s].op == acc_op::InfNeg && r[rs].op == acc_op::InfNeg)) + { + (*this)[s - 1].mark |= r[rs - 1].mark; + return *this; + } - // In the more complex scenarios, left and right may both - // be conjunctions, and Inf(x) might be a member of each - // side. Find it if it exists. - // left_inf points to the left Inf mark if any. - // right_inf points to the right Inf mark if any. - acc_word* left_inf = nullptr; - if ((*this)[s].op == acc_op::And) - { - auto start = &(*this)[s] - (*this)[s].size; - auto pos = &(*this)[s] - 1; - pop_back(); - while (pos > start) - { - if (pos->op == acc_op::Inf) - { - left_inf = pos - 1; - break; - } - pos -= pos->size + 1; - } - } - else if ((*this)[s].op == acc_op::Inf) - { - left_inf = &(*this)[s - 1]; - } + // In the more complex scenarios, left and right may both + // be conjunctions, and Inf(x) might be a member of each + // side. Find it if it exists. + // left_inf points to the left Inf mark if any. + // right_inf points to the right Inf mark if any. + acc_word* left_inf = nullptr; + if ((*this)[s].op == acc_op::And) + { + auto start = &(*this)[s] - (*this)[s].size; + auto pos = &(*this)[s] - 1; + pop_back(); + while (pos > start) + { + if (pos->op == acc_op::Inf) + { + left_inf = pos - 1; + break; + } + pos -= pos->size + 1; + } + } + else if ((*this)[s].op == acc_op::Inf) + { + left_inf = &(*this)[s - 1]; + } - acc_word* right_inf = nullptr; - auto right_end = &r.back(); - if (right_end->op == acc_op::And) - { - auto start = &r[0]; - auto pos = --right_end; - while (pos > start) - { - if (pos->op == acc_op::Inf) - { - right_inf = pos - 1; - break; - } - pos -= pos->size + 1; - } - } - else if (right_end->op == acc_op::Inf) - { - right_inf = right_end - 1; - } + acc_word* right_inf = nullptr; + auto right_end = &r.back(); + if (right_end->op == acc_op::And) + { + auto start = &r[0]; + auto pos = --right_end; + while (pos > start) + { + if (pos->op == acc_op::Inf) + { + right_inf = pos - 1; + break; + } + pos -= pos->size + 1; + } + } + else if (right_end->op == acc_op::Inf) + { + right_inf = right_end - 1; + } - if (left_inf && right_inf) - { - left_inf->mark |= right_inf->mark; - insert(this->end(), &r[0], right_inf); - insert(this->end(), right_inf + 2, right_end + 1); - } - else if (right_inf) - { - // Always insert Inf() at the very first entry. - insert(this->begin(), right_inf, right_inf + 2); - insert(this->end(), &r[0], right_inf); - insert(this->end(), right_inf + 2, right_end + 1); - } - else - { - insert(this->end(), &r[0], right_end + 1); - } + if (left_inf && right_inf) + { + left_inf->mark |= right_inf->mark; + insert(this->end(), &r[0], right_inf); + insert(this->end(), right_inf + 2, right_end + 1); + } + else if (right_inf) + { + // Always insert Inf() at the very first entry. + insert(this->begin(), right_inf, right_inf + 2); + insert(this->end(), &r[0], right_inf); + insert(this->end(), right_inf + 2, right_end + 1); + } + else + { + insert(this->end(), &r[0], right_end + 1); + } - acc_word w; - w.op = acc_op::And; - w.size = size(); - push_back(w); - return *this; + acc_word w; + w.op = acc_op::And; + w.size = size(); + push_back(w); + return *this; } acc_code& operator&=(const acc_code& r) { - if (is_t() || r.is_f()) - { - *this = r; - return *this; - } - if (is_f() || r.is_t()) - return *this; - unsigned s = size() - 1; - unsigned rs = r.size() - 1; - // Inf(a) & Inf(b) = Inf(a & b) - if (((*this)[s].op == acc_op::Inf && r[rs].op == acc_op::Inf) - || ((*this)[s].op == acc_op::InfNeg && r[rs].op == acc_op::InfNeg)) - { - (*this)[s - 1].mark |= r[rs - 1].mark; - return *this; - } + if (is_t() || r.is_f()) + { + *this = r; + return *this; + } + if (is_f() || r.is_t()) + return *this; + unsigned s = size() - 1; + unsigned rs = r.size() - 1; + // Inf(a) & Inf(b) = Inf(a & b) + if (((*this)[s].op == acc_op::Inf && r[rs].op == acc_op::Inf) + || ((*this)[s].op == acc_op::InfNeg && r[rs].op == acc_op::InfNeg)) + { + (*this)[s - 1].mark |= r[rs - 1].mark; + return *this; + } - // In the more complex scenarios, left and right may both - // be conjunctions, and Inf(x) might be a member of each - // side. Find it if it exists. - // left_inf points to the left Inf mark if any. - // right_inf points to the right Inf mark if any. - acc_word* left_inf = nullptr; - if ((*this)[s].op == acc_op::And) - { - auto start = &(*this)[s] - (*this)[s].size; - auto pos = &(*this)[s] - 1; - pop_back(); - while (pos > start) - { - if (pos->op == acc_op::Inf) - { - left_inf = pos - 1; - break; - } - pos -= pos->size + 1; - } - } - else if ((*this)[s].op == acc_op::Inf) - { - left_inf = &(*this)[s - 1]; - } + // In the more complex scenarios, left and right may both + // be conjunctions, and Inf(x) might be a member of each + // side. Find it if it exists. + // left_inf points to the left Inf mark if any. + // right_inf points to the right Inf mark if any. + acc_word* left_inf = nullptr; + if ((*this)[s].op == acc_op::And) + { + auto start = &(*this)[s] - (*this)[s].size; + auto pos = &(*this)[s] - 1; + pop_back(); + while (pos > start) + { + if (pos->op == acc_op::Inf) + { + left_inf = pos - 1; + break; + } + pos -= pos->size + 1; + } + } + else if ((*this)[s].op == acc_op::Inf) + { + left_inf = &(*this)[s - 1]; + } - const acc_word* right_inf = nullptr; - auto right_end = &r.back(); - if (right_end->op == acc_op::And) - { - auto start = &r[0]; - auto pos = --right_end; - while (pos > start) - { - if (pos->op == acc_op::Inf) - { - right_inf = pos - 1; - break; - } - pos -= pos->size + 1; - } - } - else if (right_end->op == acc_op::Inf) - { - right_inf = right_end - 1; - } + const acc_word* right_inf = nullptr; + auto right_end = &r.back(); + if (right_end->op == acc_op::And) + { + auto start = &r[0]; + auto pos = --right_end; + while (pos > start) + { + if (pos->op == acc_op::Inf) + { + right_inf = pos - 1; + break; + } + pos -= pos->size + 1; + } + } + else if (right_end->op == acc_op::Inf) + { + right_inf = right_end - 1; + } - if (left_inf && right_inf) - { - left_inf->mark |= right_inf->mark; - insert(this->end(), &r[0], right_inf); - insert(this->end(), right_inf + 2, right_end + 1); - } - else if (right_inf) - { - // Always insert Inf() at the very first entry. - insert(this->begin(), right_inf, right_inf + 2); - insert(this->end(), &r[0], right_inf); - insert(this->end(), right_inf + 2, right_end + 1); - } - else - { - insert(this->end(), &r[0], right_end + 1); - } + if (left_inf && right_inf) + { + left_inf->mark |= right_inf->mark; + insert(this->end(), &r[0], right_inf); + insert(this->end(), right_inf + 2, right_end + 1); + } + else if (right_inf) + { + // Always insert Inf() at the very first entry. + insert(this->begin(), right_inf, right_inf + 2); + insert(this->end(), &r[0], right_inf); + insert(this->end(), right_inf + 2, right_end + 1); + } + else + { + insert(this->end(), &r[0], right_end + 1); + } - acc_word w; - w.op = acc_op::And; - w.size = size(); - push_back(w); - return *this; + acc_word w; + w.op = acc_op::And; + w.size = size(); + push_back(w); + return *this; } acc_code operator&(acc_code&& r) { - acc_code res = *this; - res &= r; - return res; + acc_code res = *this; + res &= r; + return res; } acc_code operator&(const acc_code& r) { - acc_code res = *this; - res &= r; - return res; + acc_code res = *this; + res &= r; + return res; } acc_code& operator|=(acc_code&& r) { - if (is_t() || r.is_f()) - return *this; - if (is_f() || r.is_t()) - { - *this = std::move(r); - return *this; - } - unsigned s = size() - 1; - unsigned rs = r.size() - 1; - // Fin(a) | Fin(b) = Fin(a | b) - if (((*this)[s].op == acc_op::Fin && r[rs].op == acc_op::Fin) - || ((*this)[s].op == acc_op::FinNeg && r[rs].op == acc_op::FinNeg)) - { - (*this)[s - 1].mark |= r[rs - 1].mark; - return *this; - } - if ((*this)[s].op == acc_op::Or) - pop_back(); - if (r.back().op == acc_op::Or) - r.pop_back(); - insert(this->end(), r.begin(), r.end()); - acc_word w; - w.op = acc_op::Or; - w.size = size(); - push_back(w); - return *this; + if (is_t() || r.is_f()) + return *this; + if (is_f() || r.is_t()) + { + *this = std::move(r); + return *this; + } + unsigned s = size() - 1; + unsigned rs = r.size() - 1; + // Fin(a) | Fin(b) = Fin(a | b) + if (((*this)[s].op == acc_op::Fin && r[rs].op == acc_op::Fin) + || ((*this)[s].op == acc_op::FinNeg && r[rs].op == acc_op::FinNeg)) + { + (*this)[s - 1].mark |= r[rs - 1].mark; + return *this; + } + if ((*this)[s].op == acc_op::Or) + pop_back(); + if (r.back().op == acc_op::Or) + r.pop_back(); + insert(this->end(), r.begin(), r.end()); + acc_word w; + w.op = acc_op::Or; + w.size = size(); + push_back(w); + return *this; } acc_code& operator|=(const acc_code& r) { - return *this |= acc_code(r); + return *this |= acc_code(r); } acc_code operator|(acc_code&& r) { - acc_code res = *this; - res |= r; - return res; + acc_code res = *this; + res |= r; + return res; } acc_code operator|(const acc_code& r) { - acc_code res = *this; - res |= r; - return res; + acc_code res = *this; + res |= r; + return res; } acc_code& operator<<=(unsigned sets) { - if (empty()) - return *this; - unsigned pos = size(); - do - { - switch ((*this)[pos - 1].op) - { - case acc_cond::acc_op::And: - case acc_cond::acc_op::Or: - --pos; - break; - case acc_cond::acc_op::Inf: - case acc_cond::acc_op::InfNeg: - case acc_cond::acc_op::Fin: - case acc_cond::acc_op::FinNeg: - pos -= 2; - (*this)[pos].mark.id <<= sets; - break; - } - } - while (pos > 0); - return *this; + if (empty()) + return *this; + unsigned pos = size(); + do + { + switch ((*this)[pos - 1].op) + { + case acc_cond::acc_op::And: + case acc_cond::acc_op::Or: + --pos; + break; + case acc_cond::acc_op::Inf: + case acc_cond::acc_op::InfNeg: + case acc_cond::acc_op::Fin: + case acc_cond::acc_op::FinNeg: + pos -= 2; + (*this)[pos].mark.id <<= sets; + break; + } + } + while (pos > 0); + return *this; } acc_code operator<<(unsigned sets) const { - acc_code res = *this; - res <<= sets; - return res; + acc_code res = *this; + res <<= sets; + return res; } bool is_dnf() const; @@ -852,7 +852,7 @@ namespace spot // Positive values describe positive set. // A negative value x means the set -x-1 must be absent. std::vector> - missing(mark_t inf, bool accepting) const; + missing(mark_t inf, bool accepting) const; bool accepting(mark_t inf) const; @@ -883,15 +883,15 @@ namespace spot // be used to implement customized output for set numbers. std::ostream& to_html(std::ostream& os, - std::function - set_printer = nullptr) const; + std::function + set_printer = nullptr) const; // Print the acceptance as text. The set_printer function can // be used to implement customized output for set numbers. std::ostream& to_text(std::ostream& os, - std::function - set_printer = nullptr) const; + std::function + set_printer = nullptr) const; /// \brief Construct an acc_code from a string. @@ -999,7 +999,7 @@ namespace spot { unsigned s = code_.size(); return num_ == 1 && - s == 2 && code_[1].op == acc_op::Inf && code_[0].mark == all_sets(); + s == 2 && code_[1].op == acc_op::Inf && code_[0].mark == all_sets(); } bool is_co_buchi() const @@ -1016,14 +1016,14 @@ namespace spot { unsigned s = code_.size(); return (s == 0 && num_ == 0) || - (s == 2 && code_[1].op == acc_op::Inf && code_[0].mark == all_sets()); + (s == 2 && code_[1].op == acc_op::Inf && code_[0].mark == all_sets()); } bool is_generalized_co_buchi() const { unsigned s = code_.size(); return (s == 2 && - code_[1].op == acc_op::Fin && code_[0].mark == all_sets()); + code_[1].op == acc_op::Fin && code_[0].mark == all_sets()); } // Returns a number of pairs (>=0) if Rabin, or -1 else. @@ -1099,11 +1099,11 @@ namespace spot unsigned add_sets(unsigned num) { if (num == 0) - return -1U; + return -1U; unsigned j = num_; num_ += num; if (num_ > 8 * sizeof(mark_t::id)) - throw std::runtime_error("Too many acceptance sets used."); + throw std::runtime_error("Too many acceptance sets used."); all_ = all_sets_(); return j; } @@ -1145,7 +1145,7 @@ namespace spot { auto a = m; if (a == 0U) - return os; + return os; return os << m; } @@ -1164,25 +1164,25 @@ namespace spot template mark_t useless(iterator begin, iterator end) const { - mark_t::value_t u = 0U; // The set of useless marks. + mark_t::value_t u = 0U; // The set of useless marks. for (unsigned x = 0; x < num_; ++x) - { - // Skip marks that are already known to be useless. - if (u & (1 << x)) - continue; - unsigned all = all_ ^ (u | (1 << x)); - for (iterator y = begin; y != end; ++y) - { - auto v = y->id; - if (v & (1 << x)) - { - all &= v; - if (!all) - break; - } - } - u |= all; - } + { + // Skip marks that are already known to be useless. + if (u & (1 << x)) + continue; + unsigned all = all_ ^ (u | (1 << x)); + for (iterator y = begin; y != end; ++y) + { + auto v = y->id; + if (v & (1 << x)) + { + all &= v; + if (!all) + break; + } + } + u |= all; + } return u; } @@ -1190,7 +1190,7 @@ namespace spot mark_t::value_t all_sets_() const { if (num_ == 0) - return 0; + return 0; return -1U >> (8 * sizeof(mark_t::value_t) - num_); } diff --git a/spot/twa/bdddict.cc b/spot/twa/bdddict.cc index 67969d790..cb972055e 100644 --- a/spot/twa/bdddict.cc +++ b/spot/twa/bdddict.cc @@ -50,21 +50,21 @@ namespace spot // a hash; but we should ensure that no object in the hash is // constructed with p==0. anon_free_list(bdd_dict_priv* p = nullptr) - : priv_(p) + : priv_(p) { } virtual int extend(int n) override { - assert(priv_); - int b = priv_->allocate_variables(n); - free_anonymous_list_of_type::iterator i; - for (i = priv_->free_anonymous_list_of.begin(); - i != priv_->free_anonymous_list_of.end(); ++i) - if (&i->second != this) - i->second.insert(b, n); - return b; + assert(priv_); + int b = priv_->allocate_variables(n); + free_anonymous_list_of_type::iterator i; + for (i = priv_->free_anonymous_list_of.begin(); + i != priv_->free_anonymous_list_of.end(); ++i) + if (&i->second != this) + i->second.insert(b, n); + return b; } private: @@ -102,15 +102,15 @@ namespace spot fv_map::iterator sii = var_map.find(f); if (sii != var_map.end()) { - num = sii->second; + num = sii->second; } else { - num = priv_->allocate_variables(1); - var_map[f] = num; - bdd_map.resize(bdd_varnum()); - bdd_map[num].type = var; - bdd_map[num].f = f; + num = priv_->allocate_variables(1); + var_map[f] = num; + bdd_map.resize(bdd_varnum()); + bdd_map[num].type = var; + bdd_map[num].f = f; } bdd_map[num].refs.insert(for_me); return num; @@ -118,7 +118,7 @@ namespace spot int bdd_dict::has_registered_proposition(formula f, - const void* me) + const void* me) { auto ssi = var_map.find(f); if (ssi == var_map.end()) @@ -132,24 +132,24 @@ namespace spot int bdd_dict::register_acceptance_variable(formula f, - const void* for_me) + const void* for_me) { int num; // Do not build an acceptance variable that already exists. fv_map::iterator sii = acc_map.find(f); if (sii != acc_map.end()) { - num = sii->second; + num = sii->second; } else { - num = priv_->allocate_variables(1); - acc_map[f] = num; - bdd_map.resize(bdd_varnum()); - bdd_info& i = bdd_map[num]; - i.type = acc; - i.f = f; - i.clone_counts = 0; + num = priv_->allocate_variables(1); + acc_map[f] = num; + bdd_map.resize(bdd_varnum()); + bdd_info& i = bdd_map[num]; + i.type = acc; + i.f = f; + i.clone_counts = 0; } bdd_map[num].refs.insert(for_me); return num; @@ -163,9 +163,9 @@ namespace spot if (i == priv_->free_anonymous_list_of.end()) { - i = (priv_->free_anonymous_list_of.insert - (fal::value_type(for_me, - priv_->free_anonymous_list_of[nullptr]))).first; + i = (priv_->free_anonymous_list_of.insert + (fal::value_type(for_me, + priv_->free_anonymous_list_of[nullptr]))).first; } int res = i->second.register_n(n); @@ -173,8 +173,8 @@ namespace spot while (n--) { - bdd_map[res + n].type = anon; - bdd_map[res + n].refs.insert(for_me); + bdd_map[res + n].type = anon; + bdd_map[res + n].refs.insert(for_me); } return res; @@ -183,7 +183,7 @@ namespace spot void bdd_dict::register_all_variables_of(const void* from_other, - const void* for_me) + const void* for_me) { auto j = priv_->free_anonymous_list_of.find(from_other); if (j != priv_->free_anonymous_list_of.end()) @@ -191,24 +191,24 @@ namespace spot for (auto& i: bdd_map) { - ref_set& s = i.refs; - if (s.find(from_other) != s.end()) - s.insert(for_me); + ref_set& s = i.refs; + if (s.find(from_other) != s.end()) + s.insert(for_me); } } void bdd_dict::register_all_propositions_of(const void* from_other, - const void* for_me) + const void* for_me) { for (auto& i: bdd_map) { - if (i.type != var_type::var) - continue; - ref_set& s = i.refs; - if (s.find(from_other) != s.end()) - s.insert(for_me); + if (i.type != var_type::var) + continue; + ref_set& s = i.refs; + if (s.find(from_other) != s.end()) + s.insert(for_me); } } @@ -241,24 +241,24 @@ namespace spot switch (bdd_map[v].type) { case var: - f = bdd_map[v].f; - var_map.erase(f); - break; + f = bdd_map[v].f; + var_map.erase(f); + break; case acc: - f = bdd_map[v].f; - acc_map.erase(f); - break; + f = bdd_map[v].f; + acc_map.erase(f); + break; case anon: - { - bdd_dict_priv::free_anonymous_list_of_type::iterator i; - // Nobody use this variable as an anonymous variable - // anymore, so remove it entirely from the anonymous - // free list so it can be used for something else. - for (i = priv_->free_anonymous_list_of.begin(); - i != priv_->free_anonymous_list_of.end(); ++i) - i->second.remove(v, n); - break; - } + { + bdd_dict_priv::free_anonymous_list_of_type::iterator i; + // Nobody use this variable as an anonymous variable + // anymore, so remove it entirely from the anonymous + // free list so it can be used for something else. + for (i = priv_->free_anonymous_list_of.begin(); + i != priv_->free_anonymous_list_of.end(); ++i) + i->second.remove(v, n); + break; + } } // Actually release the associated BDD variables, and the // formula itself. @@ -283,39 +283,39 @@ namespace spot unsigned s = bdd_map.size(); for (unsigned i = 0; i < s; ++i) { - os << ' ' << i << ' '; - const bdd_info& r = bdd_map[i]; - switch (r.type) - { - case anon: - os << (r.refs.empty() ? "Free" : "Anon"); - break; - case acc: - os << "Acc["; - print_psl(os, r.f) << ']'; - break; - case var: - os << "Var["; - print_psl(os, r.f) << ']'; - break; - } - if (!r.refs.empty()) - { - os << " x" << r.refs.size() << " {"; - for (ref_set::const_iterator si = r.refs.begin(); - si != r.refs.end(); ++si) - os << ' ' << *si; - os << " }"; - } - os << '\n'; + os << ' ' << i << ' '; + const bdd_info& r = bdd_map[i]; + switch (r.type) + { + case anon: + os << (r.refs.empty() ? "Free" : "Anon"); + break; + case acc: + os << "Acc["; + print_psl(os, r.f) << ']'; + break; + case var: + os << "Var["; + print_psl(os, r.f) << ']'; + break; + } + if (!r.refs.empty()) + { + os << " x" << r.refs.size() << " {"; + for (ref_set::const_iterator si = r.refs.begin(); + si != r.refs.end(); ++si) + os << ' ' << *si; + os << " }"; + } + os << '\n'; } os << "Anonymous lists:\n"; bdd_dict_priv::free_anonymous_list_of_type::const_iterator ai; for (ai = priv_->free_anonymous_list_of.begin(); - ai != priv_->free_anonymous_list_of.end(); ++ai) + ai != priv_->free_anonymous_list_of.end(); ++ai) { - os << " [" << ai->first << "] "; - ai->second.dump_free_list(os) << std::endl; + os << " [" << ai->first << "] "; + ai->second.dump_free_list(os) << std::endl; } os << "Free list:\n"; priv_->dump_free_list(os); @@ -334,42 +334,42 @@ namespace spot unsigned s = bdd_map.size(); for (unsigned i = 0; i < s; ++i) { - switch (bdd_map[i].type) - { - case var: - var_seen = true; - break; - case acc: - acc_seen = true; - break; - case anon: - break; - } - refs_seen |= !bdd_map[i].refs.empty(); + switch (bdd_map[i].type) + { + case var: + var_seen = true; + break; + case acc: + acc_seen = true; + break; + case anon: + break; + } + refs_seen |= !bdd_map[i].refs.empty(); } if (var_map.empty() && acc_map.empty()) { - if (var_seen) - { - std::cerr << "var_map is empty but Var in map" << std::endl; - fail = true; - } - if (acc_seen) - { - std::cerr << "acc_map is empty but Acc in map" << std::endl; - fail = true; - } - if (refs_seen) - { - std::cerr << "maps are empty but var_refs is not" << std::endl; - fail = true; - } - if (!fail) - return; + if (var_seen) + { + std::cerr << "var_map is empty but Var in map" << std::endl; + fail = true; + } + if (acc_seen) + { + std::cerr << "acc_map is empty but Acc in map" << std::endl; + fail = true; + } + if (refs_seen) + { + std::cerr << "maps are empty but var_refs is not" << std::endl; + fail = true; + } + if (!fail) + return; } else { - std::cerr << "some maps are not empty" << std::endl; + std::cerr << "some maps are not empty" << std::endl; } dump(std::cerr); abort(); diff --git a/spot/twa/bdddict.hh b/spot/twa/bdddict.hh index 0bb364f72..33054d0c0 100644 --- a/spot/twa/bdddict.hh +++ b/spot/twa/bdddict.hh @@ -70,8 +70,8 @@ namespace spot /// BDD-variable-to-formula maps. typedef std::map vf_map; - fv_map var_map; ///< Maps atomic propositions to BDD variables - fv_map acc_map; ///< Maps acceptance conditions to BDD variables + fv_map var_map; ///< Maps atomic propositions to BDD variables + fv_map acc_map; ///< Maps acceptance conditions to BDD variables /// BDD-variable reference counts. typedef std::set ref_set; @@ -80,7 +80,7 @@ namespace spot struct bdd_info { bdd_info() : type(anon) {} var_type type; - formula f; // Used unless t==anon. + formula f; // Used unless t==anon. ref_set refs; int clone_counts; }; @@ -180,21 +180,21 @@ namespace spot template void register_all_variables_of(const void* from_other, - std::shared_ptr for_me) + std::shared_ptr for_me) { register_all_variables_of(from_other, for_me.get()); } template void register_all_variables_of(std::shared_ptr from_other, - const void* for_me) + const void* for_me) { register_all_variables_of(from_other.get(), for_me); } template void register_all_variables_of(std::shared_ptr from_other, - std::shared_ptr for_me) + std::shared_ptr for_me) { register_all_variables_of(from_other.get(), for_me.get()); } @@ -209,25 +209,25 @@ namespace spot /// is still alive. /// @{ void register_all_propositions_of(const void* from_other, - const void* for_me); + const void* for_me); template void register_all_propositions_of(const void* from_other, - std::shared_ptr for_me) + std::shared_ptr for_me) { register_all_propositions_of(from_other, for_me.get()); } template void register_all_propositions_of(std::shared_ptr from_other, - const void* for_me) + const void* for_me) { register_all_propositions_of(from_other.get(), for_me); } template void register_all_propositions_of(std::shared_ptr from_other, - std::shared_ptr for_me) + std::shared_ptr for_me) { register_all_propositions_of(from_other.get(), for_me.get()); } diff --git a/spot/twa/bddprint.cc b/spot/twa/bddprint.cc index ffccb39f0..79c89d1f2 100644 --- a/spot/twa/bddprint.cc +++ b/spot/twa/bddprint.cc @@ -58,22 +58,22 @@ namespace spot switch (ref.type) { case bdd_dict::var: - print_(o, ref.f); - break; + print_(o, ref.f); + break; case bdd_dict::acc: - if (want_acc) - { - o << "Acc["; - print_(o, ref.f) << ']'; - } - else - { - o << '"'; - print_(o, ref.f) << '"'; - } - break; + if (want_acc) + { + o << "Acc["; + print_(o, ref.f) << ']'; + } + else + { + o << '"'; + print_(o, ref.f) << '"'; + } + break; case bdd_dict::anon: - o << '?' << v; + o << '?' << v; } } @@ -85,15 +85,15 @@ namespace spot bool not_first = false; for (int v = 0; v < size; ++v) { - if (varset[v] < 0) - continue; - if (not_first) - *where << ' '; - else - not_first = true; - if (varset[v] == 0) - *where << "! "; - print_handler(*where, v); + if (varset[v] < 0) + continue; + if (not_first) + *where << ' '; + else + not_first = true; + if (varset[v] == 0) + *where << "! "; + print_handler(*where, v); } } @@ -114,11 +114,11 @@ namespace spot { for (int v = 0; v < size; ++v) if (varset[v] > 0) - { - *where << (first_done ? ", " : "{"); - print_handler(*where, v); - first_done = true; - } + { + *where << (first_done ? ", " : "{"); + print_handler(*where, v); + first_done = true; + } } std::ostream& diff --git a/spot/twa/formula2bdd.cc b/spot/twa/formula2bdd.cc index 134b648ad..d111a5101 100644 --- a/spot/twa/formula2bdd.cc +++ b/spot/twa/formula2bdd.cc @@ -33,30 +33,30 @@ namespace spot conj_to_formula(bdd b, const bdd_dict_ptr d) { if (b == bddfalse) - return formula::ff(); + return formula::ff(); std::vector v; while (b != bddtrue) - { - int var = bdd_var(b); - const bdd_dict::bdd_info& i = d->bdd_map[var]; - assert(i.type == bdd_dict::var); - formula res = i.f; + { + int var = bdd_var(b); + const bdd_dict::bdd_info& i = d->bdd_map[var]; + assert(i.type == bdd_dict::var); + formula res = i.f; - bdd high = bdd_high(b); - if (high == bddfalse) - { - res = formula::Not(res); - b = bdd_low(b); - } - else - { - // If bdd_low is not false, then b was not a conjunction. - assert(bdd_low(b) == bddfalse); - b = high; - } - assert(b != bddfalse); - v.push_back(res); - } + bdd high = bdd_high(b); + if (high == bddfalse) + { + res = formula::Not(res); + b = bdd_low(b); + } + else + { + // If bdd_low is not false, then b was not a conjunction. + assert(bdd_low(b) == bddfalse); + b = high; + } + assert(b != bddfalse); + v.push_back(res); + } return formula::And(v); } } // anonymous @@ -66,14 +66,14 @@ namespace spot { auto recurse = [&d, owner](formula f) { - return formula_to_bdd(f, d, owner); + return formula_to_bdd(f, d, owner); }; switch (f.kind()) { case op::ff: - return bddfalse; + return bddfalse; case op::tt: - return bddtrue; + return bddtrue; case op::eword: case op::Star: case op::FStar: @@ -95,32 +95,32 @@ namespace spot case op::AndNLM: case op::OrRat: case op::AndRat: - SPOT_UNIMPLEMENTED(); + SPOT_UNIMPLEMENTED(); case op::ap: - return bdd_ithvar(d->register_proposition(f, owner)); + return bdd_ithvar(d->register_proposition(f, owner)); case op::Not: - return bdd_not(recurse(f[0])); + return bdd_not(recurse(f[0])); case op::Xor: - return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_xor); + return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_xor); case op::Implies: - return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_imp); + return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_imp); case op::Equiv: - return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_biimp); + return bdd_apply(recurse(f[0]), recurse(f[1]), bddop_biimp); case op::And: case op::Or: - { - int o = bddop_and; - bdd res = bddtrue; - if (f.is(op::Or)) - { - o = bddop_or; - res = bddfalse; - } - unsigned s = f.size(); - for (unsigned n = 0; n < s; ++n) - res = bdd_apply(res, recurse(f[n]), o); - return res; - } + { + int o = bddop_and; + bdd res = bddtrue; + if (f.is(op::Or)) + { + o = bddop_or; + res = bddfalse; + } + unsigned s = f.size(); + for (unsigned n = 0; n < s; ++n) + res = bdd_apply(res, recurse(f[n]), o); + return res; + } } SPOT_UNREACHABLE(); return bddfalse; diff --git a/spot/twa/formula2bdd.hh b/spot/twa/formula2bdd.hh index 56ce4c8f2..4d5c81a60 100644 --- a/spot/twa/formula2bdd.hh +++ b/spot/twa/formula2bdd.hh @@ -44,7 +44,7 @@ namespace spot template SPOT_API bdd formula_to_bdd(formula f, const bdd_dict_ptr& d, - const std::shared_ptr& for_me) + const std::shared_ptr& for_me) { return formula_to_bdd(f, d, for_me.get()); } diff --git a/spot/twa/taatgba.cc b/spot/twa/taatgba.cc index 8b72d6be6..bb48289df 100644 --- a/spot/twa/taatgba.cc +++ b/spot/twa/taatgba.cc @@ -94,7 +94,7 @@ namespace spot { int i = *it1++ - *it2++; if (i != 0) - return i; + return i; } return 0; } @@ -162,14 +162,14 @@ namespace spot unsigned p; for (p = 0; p < pos.size() && t->condition != bddfalse; ++p) { - taa_tgba::state_set::const_iterator j; - for (j = (*pos[p])->dst->begin(); j != (*pos[p])->dst->end(); ++j) - if ((*j)->size() > 0) // Remove sink states. - ss->insert(*j); + taa_tgba::state_set::const_iterator j; + for (j = (*pos[p])->dst->begin(); j != (*pos[p])->dst->end(); ++j) + if ((*j)->size() > 0) // Remove sink states. + ss->insert(*j); - // Fill the new transition. - t->condition &= (*pos[p])->condition; - t->acceptance_conditions |= (*pos[p])->acceptance_conditions; + // Fill the new transition. + t->condition &= (*pos[p])->condition; + t->acceptance_conditions |= (*pos[p])->acceptance_conditions; } // If p != pos.size() we have found a contradiction assert(p > 0); t->dst = ss; @@ -182,54 +182,54 @@ namespace spot std::vector::iterator j; if (t->condition != bddfalse) { - i = seen_.find(b); - if (i != seen_.end()) - for (j = i->second.begin(); j != i->second.end(); ++j) - { - taa_tgba::transition* current = *j; - if (*current->dst == *t->dst - && current->condition == t->condition) - { - current->acceptance_conditions &= t->acceptance_conditions; - break; - } - if (*current->dst == *t->dst - && current->acceptance_conditions == t->acceptance_conditions) - { - current->condition |= t->condition; - break; - } - } + i = seen_.find(b); + if (i != seen_.end()) + for (j = i->second.begin(); j != i->second.end(); ++j) + { + taa_tgba::transition* current = *j; + if (*current->dst == *t->dst + && current->condition == t->condition) + { + current->acceptance_conditions &= t->acceptance_conditions; + break; + } + if (*current->dst == *t->dst + && current->acceptance_conditions == t->acceptance_conditions) + { + current->condition |= t->condition; + break; + } + } } // Mark the new transition as seen and keep it if we have not // found any contradiction and no other transition to merge // with, or delete it otherwise. if (t->condition != bddfalse - && (i == seen_.end() || j == i->second.end())) + && (i == seen_.end() || j == i->second.end())) { - seen_[b].push_back(t); - if (i != seen_.end()) - delete b; - succ_.push_back(t); + seen_[b].push_back(t); + if (i != seen_.end()) + delete b; + succ_.push_back(t); } else { - delete t->dst; - delete t; - delete b; + delete t->dst; + delete t; + delete b; } for (int i = pos.size() - 1; i >= 0; --i) { - if ((i < int(p)) - && (std::distance(pos[i], bounds[i].second) > 1 - || (i == 0 && std::distance(pos[i], bounds[i].second) == 1))) - { - ++pos[i]; - break; - } - else - pos[i] = bounds[i].first; + if ((i < int(p)) + && (std::distance(pos[i], bounds[i].second) > 1 + || (i == 0 && std::distance(pos[i], bounds[i].second) == 1))) + { + ++pos[i]; + break; + } + else + pos[i] = bounds[i].first; } } } diff --git a/spot/twa/taatgba.hh b/spot/twa/taatgba.hh index 6d8c1dab0..46e67c5b1 100644 --- a/spot/twa/taatgba.hh +++ b/spot/twa/taatgba.hh @@ -88,7 +88,7 @@ namespace spot virtual ~set_state() { if (delete_me_) - delete s_; + delete s_; } const taa_tgba::state_set* get_state() const; @@ -118,18 +118,18 @@ namespace spot typedef std::pair iterator_pair; typedef std::vector bounds_t; typedef std::unordered_map, - state_ptr_hash, state_ptr_equal> seen_map; + std::vector, + state_ptr_hash, state_ptr_equal> seen_map; struct distance_sort : public std::binary_function + const iterator_pair&, bool> { bool operator()(const iterator_pair& lhs, const iterator_pair& rhs) const { - return std::distance(lhs.first, lhs.second) < - std::distance(rhs.first, rhs.second); + return std::distance(lhs.first, lhs.second) < + std::distance(rhs.first, rhs.second); } }; @@ -150,11 +150,11 @@ namespace spot ~taa_tgba_labelled() { for (auto i: name_state_map_) - { - for (auto i2: *i.second) - delete i2; - delete i.second; - } + { + for (auto i2: *i.second) + delete i2; + delete i.second; + } } void set_init_state(const label& s) @@ -170,7 +170,7 @@ namespace spot transition* create_transition(const label& s, - const std::vector