sanity: Replace tabulars by spaces in *.cc *.hh *.hxx

* bin/autfilt.cc, bin/common_aoutput.cc, bin/common_aoutput.hh,
bin/common_finput.cc, bin/common_finput.hh, bin/common_hoaread.cc,
bin/common_output.cc, bin/common_output.hh, bin/common_post.cc,
bin/common_post.hh, bin/common_r.hh, bin/common_range.cc,
bin/common_range.hh, bin/common_setup.cc, bin/common_trans.cc,
bin/common_trans.hh, bin/dstar2tgba.cc, bin/genltl.cc,
bin/ltl2tgba.cc, bin/ltl2tgta.cc, bin/ltlcross.cc, bin/ltldo.cc,
bin/ltlfilt.cc, bin/ltlgrind.cc, bin/randaut.cc, bin/randltl.cc,
bin/spot-x.cc, spot/graph/graph.hh, spot/graph/ngraph.hh,
spot/kripke/kripkegraph.hh, spot/ltsmin/ltsmin.cc,
spot/ltsmin/ltsmin.hh, spot/misc/bareword.cc, spot/misc/bitvect.cc,
spot/misc/bitvect.hh, spot/misc/common.hh, spot/misc/escape.cc,
spot/misc/fixpool.hh, spot/misc/formater.cc, spot/misc/hash.hh,
spot/misc/intvcmp2.cc, spot/misc/intvcmp2.hh, spot/misc/intvcomp.cc,
spot/misc/intvcomp.hh, spot/misc/location.hh, spot/misc/minato.cc,
spot/misc/minato.hh, spot/misc/mspool.hh, spot/misc/optionmap.cc,
spot/misc/optionmap.hh, spot/misc/random.cc, spot/misc/random.hh,
spot/misc/satsolver.cc, spot/misc/satsolver.hh, spot/misc/timer.cc,
spot/misc/timer.hh, spot/misc/tmpfile.cc, spot/misc/trival.hh,
spot/parseaut/fmterror.cc, spot/parseaut/parsedecl.hh,
spot/parseaut/public.hh, spot/parsetl/fmterror.cc,
spot/parsetl/parsedecl.hh, spot/priv/accmap.hh, spot/priv/bddalloc.cc,
spot/priv/freelist.cc, spot/priv/trim.cc, spot/priv/weight.cc,
spot/priv/weight.hh, spot/ta/taexplicit.cc, spot/ta/taexplicit.hh,
spot/ta/taproduct.cc, spot/ta/taproduct.hh, spot/ta/tgtaexplicit.cc,
spot/ta/tgtaexplicit.hh, spot/ta/tgtaproduct.cc,
spot/ta/tgtaproduct.hh, spot/taalgos/dot.cc, spot/taalgos/dot.hh,
spot/taalgos/emptinessta.cc, spot/taalgos/emptinessta.hh,
spot/taalgos/minimize.cc, spot/taalgos/tgba2ta.cc,
spot/taalgos/tgba2ta.hh, spot/tl/apcollect.cc, spot/tl/contain.cc,
spot/tl/contain.hh, spot/tl/dot.cc, spot/tl/exclusive.cc,
spot/tl/exclusive.hh, spot/tl/formula.cc, spot/tl/formula.hh,
spot/tl/length.cc, spot/tl/mark.cc, spot/tl/mutation.cc,
spot/tl/mutation.hh, spot/tl/parse.hh, spot/tl/print.cc,
spot/tl/print.hh, spot/tl/randomltl.cc, spot/tl/randomltl.hh,
spot/tl/relabel.cc, spot/tl/relabel.hh, spot/tl/remove_x.cc,
spot/tl/simplify.cc, spot/tl/simplify.hh, spot/tl/snf.cc,
spot/tl/snf.hh, spot/tl/unabbrev.cc, spot/tl/unabbrev.hh,
spot/twa/acc.cc, spot/twa/acc.hh, spot/twa/bdddict.cc,
spot/twa/bdddict.hh, spot/twa/bddprint.cc, spot/twa/formula2bdd.cc,
spot/twa/formula2bdd.hh, spot/twa/taatgba.cc, spot/twa/taatgba.hh,
spot/twa/twa.cc, spot/twa/twa.hh, spot/twa/twagraph.cc,
spot/twa/twagraph.hh, spot/twa/twaproduct.cc, spot/twa/twaproduct.hh,
spot/twaalgos/are_isomorphic.cc, spot/twaalgos/are_isomorphic.hh,
spot/twaalgos/bfssteps.cc, spot/twaalgos/bfssteps.hh,
spot/twaalgos/cleanacc.cc, spot/twaalgos/complete.cc,
spot/twaalgos/compsusp.cc, spot/twaalgos/compsusp.hh,
spot/twaalgos/copy.cc, spot/twaalgos/cycles.cc,
spot/twaalgos/cycles.hh, spot/twaalgos/degen.cc,
spot/twaalgos/degen.hh, spot/twaalgos/determinize.cc,
spot/twaalgos/determinize.hh, spot/twaalgos/dot.cc,
spot/twaalgos/dot.hh, spot/twaalgos/dtbasat.cc,
spot/twaalgos/dtbasat.hh, spot/twaalgos/dtwasat.cc,
spot/twaalgos/dtwasat.hh, spot/twaalgos/emptiness.cc,
spot/twaalgos/emptiness.hh, spot/twaalgos/emptiness_stats.hh,
spot/twaalgos/gtec/ce.cc, spot/twaalgos/gtec/ce.hh,
spot/twaalgos/gtec/gtec.cc, spot/twaalgos/gtec/gtec.hh,
spot/twaalgos/gtec/sccstack.cc, spot/twaalgos/gtec/status.cc,
spot/twaalgos/gv04.cc, spot/twaalgos/hoa.cc, spot/twaalgos/hoa.hh,
spot/twaalgos/isdet.cc, spot/twaalgos/isunamb.cc,
spot/twaalgos/isweakscc.cc, spot/twaalgos/lbtt.cc,
spot/twaalgos/lbtt.hh, spot/twaalgos/ltl2taa.cc,
spot/twaalgos/ltl2taa.hh, spot/twaalgos/ltl2tgba_fm.cc,
spot/twaalgos/ltl2tgba_fm.hh, spot/twaalgos/magic.cc,
spot/twaalgos/magic.hh, spot/twaalgos/mask.cc, spot/twaalgos/mask.hh,
spot/twaalgos/minimize.cc, spot/twaalgos/minimize.hh,
spot/twaalgos/ndfs_result.hxx, spot/twaalgos/neverclaim.cc,
spot/twaalgos/neverclaim.hh, spot/twaalgos/postproc.cc,
spot/twaalgos/postproc.hh, spot/twaalgos/powerset.cc,
spot/twaalgos/powerset.hh, spot/twaalgos/product.cc,
spot/twaalgos/product.hh, spot/twaalgos/projrun.cc,
spot/twaalgos/projrun.hh, spot/twaalgos/randomgraph.cc,
spot/twaalgos/randomgraph.hh, spot/twaalgos/randomize.cc,
spot/twaalgos/randomize.hh, spot/twaalgos/reachiter.cc,
spot/twaalgos/reachiter.hh, spot/twaalgos/relabel.cc,
spot/twaalgos/relabel.hh, spot/twaalgos/remfin.cc,
spot/twaalgos/remprop.cc, spot/twaalgos/sbacc.cc,
spot/twaalgos/sccfilter.cc, spot/twaalgos/sccfilter.hh,
spot/twaalgos/sccinfo.cc, spot/twaalgos/sccinfo.hh,
spot/twaalgos/se05.cc, spot/twaalgos/se05.hh,
spot/twaalgos/sepsets.cc, spot/twaalgos/simulation.cc,
spot/twaalgos/simulation.hh, spot/twaalgos/stats.cc,
spot/twaalgos/stats.hh, spot/twaalgos/strength.cc,
spot/twaalgos/strength.hh, spot/twaalgos/stripacc.cc,
spot/twaalgos/stutter.cc, spot/twaalgos/stutter.hh,
spot/twaalgos/tau03.cc, spot/twaalgos/tau03opt.cc,
spot/twaalgos/tau03opt.hh, spot/twaalgos/totgba.cc,
spot/twaalgos/translate.cc, spot/twaalgos/word.cc, tests/core/acc.cc,
tests/core/bitvect.cc, tests/core/checkpsl.cc, tests/core/checkta.cc,
tests/core/consterm.cc, tests/core/emptchk.cc, tests/core/equalsf.cc,
tests/core/graph.cc, tests/core/ikwiad.cc, tests/core/intvcmp2.cc,
tests/core/intvcomp.cc, tests/core/kind.cc, tests/core/kripkecat.cc,
tests/core/ltlrel.cc, tests/core/ngraph.cc, tests/core/randtgba.cc,
tests/core/readltl.cc, tests/core/reduc.cc, tests/core/safra.cc,
tests/core/syntimpl.cc, tests/ltsmin/modelcheck.cc: Replace tabulars by
8 spaces.
* tests/sanity/style.test: Add checks for no tabulars in *.cc *.hh *.hxx
This commit is contained in:
Laurent XU 2016-03-09 00:23:20 +01:00 committed by Alexandre Duret-Lutz
parent 1eee12b8b4
commit f7e7b4f14e
239 changed files with 25359 additions and 25355 deletions

View file

@ -363,9 +363,9 @@ parse_opt(int key, char* arg, struct argp_state*)
break; break;
case 'x': case 'x':
{ {
const char* opt = extra_options.parse_options(arg); const char* opt = extra_options.parse_options(arg);
if (opt) if (opt)
error(2, 0, "failed to parse --options near '%s'", opt); error(2, 0, "failed to parse --options near '%s'", opt);
} }
break; break;
case OPT_AP_N: case OPT_AP_N:
@ -376,15 +376,15 @@ parse_opt(int key, char* arg, struct argp_state*)
break; break;
case OPT_ACCEPT_WORD: case OPT_ACCEPT_WORD:
try try
{ {
opt->acc_words.push_back(spot::parse_word(arg, opt->dict) opt->acc_words.push_back(spot::parse_word(arg, opt->dict)
->as_automaton()); ->as_automaton());
} }
catch (const spot::parse_error& e) catch (const spot::parse_error& e)
{ {
error(2, 0, "failed to parse the argument of --accept-word:\n%s", error(2, 0, "failed to parse the argument of --accept-word:\n%s",
e.what()); e.what());
} }
break; break;
case OPT_ARE_ISOMORPHIC: case OPT_ARE_ISOMORPHIC:
opt->are_isomorphic = read_automaton(arg, opt->dict); opt->are_isomorphic = read_automaton(arg, opt->dict);
@ -420,27 +420,27 @@ parse_opt(int key, char* arg, struct argp_state*)
break; break;
case OPT_EQUIVALENT_TO: case OPT_EQUIVALENT_TO:
if (opt->equivalent_pos) 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_pos = read_automaton(arg, opt->dict);
opt->equivalent_neg = opt->equivalent_neg =
spot::dtwa_complement(ensure_deterministic(opt->equivalent_pos)); spot::dtwa_complement(ensure_deterministic(opt->equivalent_pos));
break; break;
case OPT_INSTUT: case OPT_INSTUT:
if (!arg || (arg[0] == '1' && arg[1] == 0)) if (!arg || (arg[0] == '1' && arg[1] == 0))
opt_instut = 1; opt_instut = 1;
else if (arg[0] == '2' && arg[1] == 0) else if (arg[0] == '2' && arg[1] == 0)
opt_instut = 2; opt_instut = 2;
else else
error(2, 0, "unknown argument for --instut: %s", arg); error(2, 0, "unknown argument for --instut: %s", arg);
break; break;
case OPT_INCLUDED_IN: case OPT_INCLUDED_IN:
{ {
auto aut = ensure_deterministic(read_automaton(arg, opt->dict)); auto aut = ensure_deterministic(read_automaton(arg, opt->dict));
aut = spot::dtwa_complement(aut); aut = spot::dtwa_complement(aut);
if (!opt->included_in) if (!opt->included_in)
opt->included_in = aut; opt->included_in = aut;
else else
opt->included_in = spot::product_or(opt->included_in, aut); opt->included_in = spot::product_or(opt->included_in, aut);
} }
break; break;
case OPT_INTERSECT: case OPT_INTERSECT:
@ -472,18 +472,18 @@ parse_opt(int key, char* arg, struct argp_state*)
break; break;
case OPT_MASK_ACC: case OPT_MASK_ACC:
{ {
for (auto res : to_longs(arg)) for (auto res : to_longs(arg))
{ {
if (res < 0) if (res < 0)
error(2, 0, "acceptance sets should be non-negative:" error(2, 0, "acceptance sets should be non-negative:"
" --mask-acc=%ld", res); " --mask-acc=%ld", res);
if (static_cast<unsigned long>(res) if (static_cast<unsigned long>(res)
> sizeof(spot::acc_cond::mark_t::value_t)) > sizeof(spot::acc_cond::mark_t::value_t))
error(2, 0, "this implementation does not support that many" error(2, 0, "this implementation does not support that many"
" acceptance sets: --mask-acc=%ld", res); " acceptance sets: --mask-acc=%ld", res);
opt_mask_acc.set(res); opt_mask_acc.set(res);
} }
break; break;
} }
case OPT_KEEP_STATES: case OPT_KEEP_STATES:
{ {
@ -491,71 +491,71 @@ parse_opt(int key, char* arg, struct argp_state*)
if (!values.empty()) if (!values.empty())
opt_keep_states_initial = values[0]; opt_keep_states_initial = values[0];
for (auto res : values) for (auto res : values)
{ {
if (res < 0) if (res < 0)
error(2, 0, "state ids should be non-negative:" error(2, 0, "state ids should be non-negative:"
" --mask-acc=%ld", res); " --mask-acc=%ld", res);
// We don't know yet how many states the automata contain. // We don't know yet how many states the automata contain.
if (opt_keep_states.size() <= static_cast<unsigned long>(res)) if (opt_keep_states.size() <= static_cast<unsigned long>(res))
opt_keep_states.resize(res + 1, false); opt_keep_states.resize(res + 1, false);
opt_keep_states[res] = true; opt_keep_states[res] = true;
} }
opt_rem_unreach = true; opt_rem_unreach = true;
break; break;
} }
case OPT_PRODUCT_AND: case OPT_PRODUCT_AND:
{ {
auto a = read_automaton(arg, opt->dict); auto a = read_automaton(arg, opt->dict);
if (!opt->product_and) if (!opt->product_and)
opt->product_and = std::move(a); opt->product_and = std::move(a);
else else
opt->product_and = spot::product(std::move(opt->product_and), opt->product_and = spot::product(std::move(opt->product_and),
std::move(a)); std::move(a));
} }
break; break;
case OPT_PRODUCT_OR: case OPT_PRODUCT_OR:
{ {
auto a = read_automaton(arg, opt->dict); auto a = read_automaton(arg, opt->dict);
if (!opt->product_or) if (!opt->product_or)
opt->product_or = std::move(a); opt->product_or = std::move(a);
else else
opt->product_or = spot::product_or(std::move(opt->product_or), opt->product_or = spot::product_or(std::move(opt->product_or),
std::move(a)); std::move(a));
} }
break; break;
case OPT_RANDOMIZE: case OPT_RANDOMIZE:
if (arg) if (arg)
{ {
for (auto p = arg; *p; ++p) for (auto p = arg; *p; ++p)
switch (*p) switch (*p)
{ {
case 's': case 's':
randomize_st = true; randomize_st = true;
break; break;
case 't': case 't':
randomize_tr = true; randomize_tr = true;
break; break;
default: default:
error(2, 0, "unknown argument for --randomize: '%c'", *p); error(2, 0, "unknown argument for --randomize: '%c'", *p);
} }
} }
else else
{ {
randomize_tr = true; randomize_tr = true;
randomize_st = true; randomize_st = true;
} }
break; break;
case OPT_REJECT_WORD: case OPT_REJECT_WORD:
try try
{ {
opt->rej_words.push_back(spot::parse_word(arg, opt->dict) opt->rej_words.push_back(spot::parse_word(arg, opt->dict)
->as_automaton()); ->as_automaton());
} }
catch (const spot::parse_error& e) catch (const spot::parse_error& e)
{ {
error(2, 0, "failed to parse the argument of --reject-word:\n%s", error(2, 0, "failed to parse the argument of --reject-word:\n%s",
e.what()); e.what());
} }
break; break;
case OPT_REM_AP: case OPT_REM_AP:
opt->rem_ap.add_ap(arg); opt->rem_ap.add_ap(arg);
@ -621,7 +621,7 @@ namespace
int int
process_automaton(const spot::const_parsed_aut_ptr& haut, process_automaton(const spot::const_parsed_aut_ptr& haut,
const char* filename) const char* filename)
{ {
spot::stopwatch sw; spot::stopwatch sw;
sw.start(); sw.start();
@ -630,30 +630,30 @@ namespace
// never modify the original automaton (e.g. with // never modify the original automaton (e.g. with
// merge_edges()) and the statistics about it make sense. // merge_edges()) and the statistics about it make sense.
auto aut = ((automaton_format == Stats) || opt_name) auto aut = ((automaton_format == Stats) || opt_name)
? spot::make_twa_graph(haut->aut, spot::twa::prop_set::all()) ? spot::make_twa_graph(haut->aut, spot::twa::prop_set::all())
: haut->aut; : haut->aut;
// Preprocessing. // Preprocessing.
if (opt_stripacc) if (opt_stripacc)
spot::strip_acceptance_here(aut); spot::strip_acceptance_here(aut);
if (opt_merge) if (opt_merge)
aut->merge_edges(); aut->merge_edges();
if (opt_clean_acc || opt_rem_fin) if (opt_clean_acc || opt_rem_fin)
cleanup_acceptance_here(aut); cleanup_acceptance_here(aut);
if (opt_sep_sets) if (opt_sep_sets)
separate_sets_here(aut); separate_sets_here(aut);
if (opt_complement_acc) if (opt_complement_acc)
aut->set_acceptance(aut->acc().num_sets(), aut->set_acceptance(aut->acc().num_sets(),
aut->get_acceptance().complement()); aut->get_acceptance().complement());
if (opt_rem_fin) if (opt_rem_fin)
aut = remove_fin(aut); aut = remove_fin(aut);
if (opt_dnf_acc) if (opt_dnf_acc)
aut->set_acceptance(aut->acc().num_sets(), aut->set_acceptance(aut->acc().num_sets(),
aut->get_acceptance().to_dnf()); aut->get_acceptance().to_dnf());
if (opt_cnf_acc) if (opt_cnf_acc)
aut->set_acceptance(aut->acc().num_sets(), aut->set_acceptance(aut->acc().num_sets(),
aut->get_acceptance().to_cnf()); aut->get_acceptance().to_cnf());
// Filters. // Filters.
@ -664,46 +664,46 @@ namespace
matched &= opt_accsets.contains(aut->acc().num_sets()); matched &= opt_accsets.contains(aut->acc().num_sets());
matched &= opt_ap_n.contains(aut->ap().size()); matched &= opt_ap_n.contains(aut->ap().size());
if (opt_is_complete) if (opt_is_complete)
matched &= is_complete(aut); matched &= is_complete(aut);
if (opt_is_deterministic) if (opt_is_deterministic)
matched &= is_deterministic(aut); matched &= is_deterministic(aut);
if (opt_is_deterministic) if (opt_is_deterministic)
matched &= is_deterministic(aut); matched &= is_deterministic(aut);
else if (opt_is_unambiguous) else if (opt_is_unambiguous)
matched &= is_unambiguous(aut); matched &= is_unambiguous(aut);
if (opt_is_terminal) if (opt_is_terminal)
matched &= is_terminal_automaton(aut); matched &= is_terminal_automaton(aut);
else if (opt_is_weak) else if (opt_is_weak)
matched &= is_weak_automaton(aut); matched &= is_weak_automaton(aut);
else if (opt_is_inherently_weak) else if (opt_is_inherently_weak)
matched &= is_inherently_weak_automaton(aut); matched &= is_inherently_weak_automaton(aut);
if (opt->are_isomorphic) if (opt->are_isomorphic)
matched &= opt->isomorphism_checker->is_isomorphic(aut); matched &= opt->isomorphism_checker->is_isomorphic(aut);
if (opt_is_empty) if (opt_is_empty)
matched &= aut->is_empty(); matched &= aut->is_empty();
if (opt->intersect) if (opt->intersect)
matched &= !spot::product(aut, opt->intersect)->is_empty(); matched &= !spot::product(aut, opt->intersect)->is_empty();
if (opt->included_in) 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) if (opt->equivalent_pos)
matched &= spot::product(aut, opt->equivalent_neg)->is_empty() matched &= spot::product(aut, opt->equivalent_neg)->is_empty()
&& spot::product(dtwa_complement(ensure_deterministic(aut)), && spot::product(dtwa_complement(ensure_deterministic(aut)),
opt->equivalent_pos)->is_empty(); opt->equivalent_pos)->is_empty();
if (matched && !opt->acc_words.empty()) if (matched && !opt->acc_words.empty())
for (auto& word_aut: opt->acc_words) for (auto& word_aut: opt->acc_words)
if (spot::product(aut, word_aut)->is_empty()) if (spot::product(aut, word_aut)->is_empty())
{ {
matched = false; matched = false;
break; break;
} }
if (matched && !opt->rej_words.empty()) if (matched && !opt->rej_words.empty())
for (auto& word_aut: opt->rej_words) for (auto& word_aut: opt->rej_words)
if (!spot::product(aut, word_aut)->is_empty()) if (!spot::product(aut, word_aut)->is_empty())
{ {
matched = false; matched = false;
break; break;
} }
// Drop or keep matched automata depending on the --invert option // Drop or keep matched automata depending on the --invert option
if (matched == opt_invert) if (matched == opt_invert)
@ -712,65 +712,65 @@ namespace
// Postprocessing. // Postprocessing.
if (opt_mask_acc) 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()) 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()) if (!opt->rem_ap.empty())
aut = opt->rem_ap.strip(aut); aut = opt->rem_ap.strip(aut);
if (opt_destut) if (opt_destut)
aut = spot::closure(std::move(aut)); aut = spot::closure(std::move(aut));
if (opt_instut == 1) if (opt_instut == 1)
aut = spot::sl(std::move(aut)); aut = spot::sl(std::move(aut));
else if (opt_instut == 2) else if (opt_instut == 2)
aut = spot::sl2(std::move(aut)); aut = spot::sl2(std::move(aut));
if (!opt_keep_states.empty()) 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) if (opt_rem_dead)
aut->purge_dead_states(); aut->purge_dead_states();
else if (opt_rem_unreach) else if (opt_rem_unreach)
aut->purge_unreachable_states(); aut->purge_unreachable_states();
if (opt->product_and) 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) 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) if (opt_decompose_strength)
{ {
aut = decompose_strength(aut, opt_decompose_strength); aut = decompose_strength(aut, opt_decompose_strength);
if (!aut) if (!aut)
return 0; return 0;
} }
if (opt_sat_minimize) if (opt_sat_minimize)
{ {
aut = spot::sat_minimize(aut, opt_sat_minimize, sbacc); aut = spot::sat_minimize(aut, opt_sat_minimize, sbacc);
if (!aut) if (!aut)
return 0; return 0;
} }
if (opt_complement) if (opt_complement)
aut = spot::dtwa_complement(ensure_deterministic(aut)); aut = spot::dtwa_complement(ensure_deterministic(aut));
aut = post.run(aut, nullptr); aut = post.run(aut, nullptr);
if (randomize_st || randomize_tr) 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(); const double conversion_time = sw.stop();
if (opt->uniq) if (opt->uniq)
{ {
auto tmp = auto tmp =
spot::canonicalize(make_twa_graph(aut, spot::canonicalize(make_twa_graph(aut,
spot::twa::prop_set::all())); spot::twa::prop_set::all()));
if (!opt->uniq->emplace(tmp->edge_vector().begin() + 1, if (!opt->uniq->emplace(tmp->edge_vector().begin() + 1,
tmp->edge_vector().end()).second) tmp->edge_vector().end()).second)
return 0; return 0;
} }
++match_count; ++match_count;
@ -778,7 +778,7 @@ namespace
printer.print(aut, nullptr, filename, -1, conversion_time, haut); printer.print(aut, nullptr, filename, -1, conversion_time, haut);
if (opt_max_count >= 0 && match_count >= opt_max_count) if (opt_max_count >= 0 && match_count >= opt_max_count)
abort_run = true; abort_run = true;
return 0; return 0;
} }
@ -796,19 +796,19 @@ namespace
auto hp = spot::automaton_stream_parser(filename, opt_parse); auto hp = spot::automaton_stream_parser(filename, opt_parse);
int err = 0; int err = 0;
while (!abort_run) while (!abort_run)
{ {
auto haut = hp.parse(opt->dict); auto haut = hp.parse(opt->dict);
if (!haut->aut && haut->errors.empty()) if (!haut->aut && haut->errors.empty())
break; break;
if (haut->format_errors(std::cerr)) if (haut->format_errors(std::cerr))
err = 2; err = 2;
if (!haut->aut) if (!haut->aut)
error(2, 0, "failed to read automaton from %s", filename); error(2, 0, "failed to read automaton from %s", filename);
else if (haut->aborted) else if (haut->aborted)
err = std::max(err, aborted(haut, filename)); err = std::max(err, aborted(haut, filename));
else else
process_automaton(haut, filename); process_automaton(haut, filename);
} }
return err; return err;
} }
}; };
@ -820,7 +820,7 @@ main(int argc, char** argv)
setup(argv); setup(argv);
const argp ap = { options, parse_opt, "[FILENAMES...]", const argp ap = { options, parse_opt, "[FILENAMES...]",
argp_program_doc, children, nullptr, nullptr }; argp_program_doc, children, nullptr, nullptr };
try try
{ {
@ -834,23 +834,23 @@ main(int argc, char** argv)
pref = spot::postprocessor::Any; pref = spot::postprocessor::Any;
type = spot::postprocessor::Generic; type = spot::postprocessor::Generic;
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
exit(err); exit(err);
if (level_set && !pref_set) if (level_set && !pref_set)
pref = spot::postprocessor::Small; pref = spot::postprocessor::Small;
if (pref_set && !level_set) if (pref_set && !level_set)
level = spot::postprocessor::High; level = spot::postprocessor::High;
if (jobs.empty()) if (jobs.empty())
jobs.emplace_back("-", true); jobs.emplace_back("-", true);
if (opt->are_isomorphic) if (opt->are_isomorphic)
{ {
if (opt_merge) if (opt_merge)
opt->are_isomorphic->merge_edges(); opt->are_isomorphic->merge_edges();
opt->isomorphism_checker = std::unique_ptr<spot::isomorphism_checker> opt->isomorphism_checker = std::unique_ptr<spot::isomorphism_checker>
(new spot::isomorphism_checker(opt->are_isomorphic)); (new spot::isomorphism_checker(opt->are_isomorphic));
} }
spot::srand(opt_seed); spot::srand(opt_seed);
@ -862,7 +862,7 @@ main(int argc, char** argv)
hoa_processor processor(post); hoa_processor processor(post);
if (processor.run()) if (processor.run())
return 2; return 2;
} }
catch (const std::runtime_error& e) catch (const std::runtime_error& e)
{ {

View file

@ -136,7 +136,7 @@ static const argp_option options[] =
}; };
const struct argp aoutput_argp = { options, parse_opt_aoutput, nullptr, nullptr, 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 // Those can be overridden by individual tools. E.g. randaut has no
// notion of input file, so %F and %L represent something else. // 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, 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[] = 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, 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*) 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': case 's':
automaton_format = Spin; automaton_format = Spin;
if (type != spot::postprocessor::Monitor) if (type != spot::postprocessor::Monitor)
type = spot::postprocessor::BA; type = spot::postprocessor::BA;
automaton_format_opt = arg; automaton_format_opt = arg;
break; break;
case OPT_CHECK: case OPT_CHECK:
automaton_format = Hoa; automaton_format = Hoa;
if (arg) if (arg)
opt_check |= XARGMATCH("--check", arg, check_args, check_types); opt_check |= XARGMATCH("--check", arg, check_args, check_types);
else else
opt_check |= check_all; opt_check |= check_all;
break; break;
case OPT_LBTT: case OPT_LBTT:
automaton_format = 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 // because print_lbtt will raise an exception anyway. The
// error message is slightly better in the current way. // error message is slightly better in the current way.
if (arg && (arg[0] != 't' || arg[1] != 0)) 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; break;
case OPT_NAME: case OPT_NAME:
opt_name = arg; opt_name = arg;
break; break;
case OPT_STATS: case OPT_STATS:
if (!*arg) if (!*arg)
error(2, 0, "empty format string for --stats"); error(2, 0, "empty format string for --stats");
stats = arg; stats = arg;
automaton_format = Stats; automaton_format = Stats;
break; break;
@ -288,23 +288,23 @@ void setup_default_output_format()
if (auto val = getenv("SPOT_DEFAULT_FORMAT")) if (auto val = getenv("SPOT_DEFAULT_FORMAT"))
{ {
static char const *const args[] = static char const *const args[] =
{ {
"dot", "hoa", "hoaf", nullptr "dot", "hoa", "hoaf", nullptr
}; };
static automaton_format_t const format[] = static automaton_format_t const format[] =
{ {
Dot, Hoa, Hoa Dot, Hoa, Hoa
}; };
auto eq = strchr(val, '='); auto eq = strchr(val, '=');
if (eq) if (eq)
{ {
val = strndup(val, eq - val); val = strndup(val, eq - val);
automaton_format_opt = eq + 1; automaton_format_opt = eq + 1;
} }
ARGMATCH_VERIFY(args, format); ARGMATCH_VERIFY(args, format);
automaton_format = XARGMATCH("SPOT_DEFAULT_FORMAT", val, args, format); automaton_format = XARGMATCH("SPOT_DEFAULT_FORMAT", val, args, format);
if (eq) if (eq)
free(val); free(val);
} }
} }
@ -320,24 +320,24 @@ automaton_printer::automaton_printer(stat_style input)
void void
automaton_printer::print(const spot::twa_graph_ptr& aut, automaton_printer::print(const spot::twa_graph_ptr& aut,
spot::formula f, spot::formula f,
// Input location for errors and statistics. // Input location for errors and statistics.
const char* filename, const char* filename,
int loc, int loc,
// Time and input automaton for statistics // Time and input automaton for statistics
double time, double time,
const spot::const_parsed_aut_ptr& haut, const spot::const_parsed_aut_ptr& haut,
const char* csv_prefix, const char* csv_prefix,
const char* csv_suffix) const char* csv_suffix)
{ {
if (opt_check) if (opt_check)
{ {
if (opt_check & check_stutter) if (opt_check & check_stutter)
spot::check_stutter_invariance(aut, f); spot::check_stutter_invariance(aut, f);
if (opt_check & check_unambiguous) if (opt_check & check_unambiguous)
spot::check_unambiguous(aut); spot::check_unambiguous(aut);
if (opt_check & check_strength) if (opt_check & check_strength)
spot::check_strength(aut); spot::check_strength(aut);
} }
// Name the output automaton. // Name the output automaton.
@ -353,11 +353,11 @@ automaton_printer::print(const spot::twa_graph_ptr& aut,
{ {
outputname.str(""); outputname.str("");
outputnamer.print(haut, aut, f, filename, loc, time, outputnamer.print(haut, aut, f, filename, loc, time,
csv_prefix, csv_suffix); csv_prefix, csv_suffix);
std::string fname = outputname.str(); std::string fname = outputname.str();
auto p = outputfiles.emplace(fname, nullptr); auto p = outputfiles.emplace(fname, nullptr);
if (p.second) 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(); out = &p.first->second->ostream();
} }
@ -383,7 +383,7 @@ automaton_printer::print(const spot::twa_graph_ptr& aut,
case Stats: case Stats:
statistics.set_output(*out); statistics.set_output(*out);
statistics.print(haut, aut, f, filename, loc, time, statistics.print(haut, aut, f, filename, loc, time,
csv_prefix, csv_suffix) << '\n'; csv_prefix, csv_suffix) << '\n';
break; break;
} }
flush_cout(); flush_cout();

View file

@ -75,25 +75,25 @@ class hoa_stat_printer: protected spot::stat_printer
{ {
public: public:
hoa_stat_printer(std::ostream& os, const char* format, hoa_stat_printer(std::ostream& os, const char* format,
stat_style input = no_input) stat_style input = no_input)
: spot::stat_printer(os, format) : spot::stat_printer(os, format)
{ {
if (input == aut_input) if (input == aut_input)
{ {
declare('A', &haut_acc_); declare('A', &haut_acc_);
declare('C', &haut_scc_); declare('C', &haut_scc_);
declare('E', &haut_edges_); declare('E', &haut_edges_);
declare('G', &haut_gen_acc_); declare('G', &haut_gen_acc_);
declare('M', &haut_name_); declare('M', &haut_name_);
declare('S', &haut_states_); declare('S', &haut_states_);
declare('T', &haut_trans_); declare('T', &haut_trans_);
} }
declare('<', &csv_prefix_); declare('<', &csv_prefix_);
declare('>', &csv_suffix_); declare('>', &csv_suffix_);
declare('F', &filename_); declare('F', &filename_);
declare('L', &location_); declare('L', &location_);
if (input != ltl_input) if (input != ltl_input)
declare('f', &filename_); // Override the formula printer. declare('f', &filename_); // Override the formula printer.
declare('m', &aut_name_); declare('m', &aut_name_);
declare('w', &aut_word_); declare('w', &aut_word_);
} }
@ -107,93 +107,93 @@ public:
/// to be output. /// to be output.
std::ostream& std::ostream&
print(const spot::const_parsed_aut_ptr& haut, print(const spot::const_parsed_aut_ptr& haut,
const spot::const_twa_graph_ptr& aut, const spot::const_twa_graph_ptr& aut,
spot::formula f, spot::formula f,
const char* filename, int loc, double run_time, const char* filename, int loc, double run_time,
const char* csv_prefix, const char* csv_suffix) const char* csv_prefix, const char* csv_suffix)
{ {
filename_ = filename ? filename : ""; filename_ = filename ? filename : "";
csv_prefix_ = csv_prefix ? csv_prefix : ""; csv_prefix_ = csv_prefix ? csv_prefix : "";
csv_suffix_ = csv_suffix ? csv_suffix : ""; csv_suffix_ = csv_suffix ? csv_suffix : "";
if (loc >= 0 && has('L')) if (loc >= 0 && has('L'))
{ {
std::ostringstream os; std::ostringstream os;
os << loc; os << loc;
location_ = os.str(); location_ = os.str();
} }
if (haut) if (haut)
{ {
if (loc < 0 && has('L')) if (loc < 0 && has('L'))
{ {
std::ostringstream os; std::ostringstream os;
os << haut->loc; os << haut->loc;
location_ = os.str(); location_ = os.str();
} }
if (has('T')) if (has('T'))
{ {
spot::twa_sub_statistics s = sub_stats_reachable(haut->aut); spot::twa_sub_statistics s = sub_stats_reachable(haut->aut);
haut_states_ = s.states; haut_states_ = s.states;
haut_edges_ = s.edges; haut_edges_ = s.edges;
haut_trans_ = s.transitions; haut_trans_ = s.transitions;
} }
else if (has('E')) else if (has('E'))
{ {
spot::twa_sub_statistics s = sub_stats_reachable(haut->aut); spot::twa_sub_statistics s = sub_stats_reachable(haut->aut);
haut_states_ = s.states; haut_states_ = s.states;
haut_edges_ = s.edges; haut_edges_ = s.edges;
} }
if (has('M')) if (has('M'))
{ {
auto n = haut->aut->get_named_prop<std::string>("automaton-name"); auto n = haut->aut->get_named_prop<std::string>("automaton-name");
if (n) if (n)
haut_name_ = *n; haut_name_ = *n;
else else
haut_name_.val().clear(); haut_name_.val().clear();
} }
if (has('S')) if (has('S'))
haut_states_ = haut->aut->num_states(); haut_states_ = haut->aut->num_states();
if (has('A')) if (has('A'))
haut_acc_ = haut->aut->acc().num_sets(); haut_acc_ = haut->aut->acc().num_sets();
if (has('C')) if (has('C'))
haut_scc_ = spot::scc_info(haut->aut).scc_count(); haut_scc_ = spot::scc_info(haut->aut).scc_count();
if (has('G')) if (has('G'))
{ {
std::ostringstream os; std::ostringstream os;
os << haut->aut->get_acceptance(); os << haut->aut->get_acceptance();
haut_gen_acc_ = os.str(); haut_gen_acc_ = os.str();
} }
} }
if (has('m')) if (has('m'))
{ {
auto n = aut->get_named_prop<std::string>("automaton-name"); auto n = aut->get_named_prop<std::string>("automaton-name");
if (n) if (n)
aut_name_ = *n; aut_name_ = *n;
else else
aut_name_.val().clear(); aut_name_.val().clear();
} }
if (has('w')) if (has('w'))
{ {
auto res = spot::couvreur99(aut)->check(); auto res = spot::couvreur99(aut)->check();
if (res) if (res)
{ {
auto run = res->accepting_run(); auto run = res->accepting_run();
assert(run); assert(run);
spot::twa_word w(run->reduce()); spot::twa_word w(run->reduce());
w.simplify(); w.simplify();
std::ostringstream out; std::ostringstream out;
out << w; out << w;
aut_word_ = out.str(); aut_word_ = out.str();
} }
else else
{ {
aut_word_.val().clear(); aut_word_.val().clear();
} }
} }
return this->spot::stat_printer::print(aut, f, run_time); return this->spot::stat_printer::print(aut, f, run_time);
} }
@ -230,15 +230,15 @@ public:
void void
print(const spot::twa_graph_ptr& aut, print(const spot::twa_graph_ptr& aut,
spot::formula f = nullptr, spot::formula f = nullptr,
// Input location for errors and statistics. // Input location for errors and statistics.
const char* filename = nullptr, const char* filename = nullptr,
int loc = -1, int loc = -1,
// Time and input automaton for statistics // Time and input automaton for statistics
double time = 0.0, double time = 0.0,
const spot::const_parsed_aut_ptr& haut = nullptr, const spot::const_parsed_aut_ptr& haut = nullptr,
const char* csv_prefix = nullptr, const char* csv_prefix = nullptr,
const char* csv_suffix = nullptr); const char* csv_suffix = nullptr);
void add_stat(char c, const spot::printable* p); void add_stat(char c, const spot::printable* p);
}; };

View file

@ -49,8 +49,8 @@ static const argp_option options[] =
}; };
const struct argp finput_argp = { options, parse_opt_finput, const struct argp finput_argp = { options, parse_opt_finput,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr }; nullptr, nullptr };
int int
parse_opt_finput(int key, char* arg, struct argp_state*) parse_opt_finput(int key, char* arg, struct argp_state*)
@ -105,15 +105,15 @@ job_processor::~job_processor()
int int
job_processor::process_string(const std::string& input, job_processor::process_string(const std::string& input,
const char* filename, const char* filename,
int linenum) int linenum)
{ {
auto pf = parse_formula(input); auto pf = parse_formula(input);
if (!pf.f || !pf.errors.empty()) if (!pf.f || !pf.errors.empty())
{ {
if (filename) 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); pf.format_errors(std::cerr);
return 1; return 1;
} }
@ -122,7 +122,7 @@ job_processor::process_string(const std::string& input,
int int
job_processor::process_stream(std::istream& is, job_processor::process_stream(std::istream& is,
const char* filename) const char* filename)
{ {
int error = 0; int error = 0;
int linenum = 1; int linenum = 1;
@ -141,148 +141,148 @@ job_processor::process_stream(std::istream& is,
while (!abort_run && std::getline(is, line)) while (!abort_run && std::getline(is, line))
if (!line.empty()) if (!line.empty())
{ {
if (col_to_read == 0) if (col_to_read == 0)
{ {
error |= process_string(line, filename, linenum++); error |= process_string(line, filename, linenum++);
} }
else // We are reading column COL_TO_READ in a CSV file. else // We are reading column COL_TO_READ in a CSV file.
{ {
// If the line we have read contains an odd number // If the line we have read contains an odd number
// of double-quotes, then it is an incomplete CSV line // of double-quotes, then it is an incomplete CSV line
// that should be completed by the next lines. // that should be completed by the next lines.
unsigned dquotes = 0; unsigned dquotes = 0;
std::string fullline; std::string fullline;
unsigned csvlines = 0; unsigned csvlines = 0;
do do
{ {
++csvlines; ++csvlines;
size_t s = line.size(); size_t s = line.size();
for (unsigned i = 0; i < s; ++i) for (unsigned i = 0; i < s; ++i)
dquotes += line[i] == '"'; dquotes += line[i] == '"';
if (fullline.empty()) if (fullline.empty())
fullline = line; fullline = line;
else else
(fullline += '\n') += line; (fullline += '\n') += line;
if (!(dquotes &= 1)) if (!(dquotes &= 1))
break; break;
} }
while (std::getline(is, line)); while (std::getline(is, line));
if (dquotes) if (dquotes)
error_at_line(2, errno, filename, linenum, error_at_line(2, errno, filename, linenum,
"mismatched double-quote, " "mismatched double-quote, "
"reached EOF while parsing this line"); "reached EOF while parsing this line");
// Now that we have a full CSV line, extract the right // Now that we have a full CSV line, extract the right
// column. // column.
const char* str = fullline.c_str(); const char* str = fullline.c_str();
const char* col1_start = str; const char* col1_start = str;
// Delimiters for the extracted column. // Delimiters for the extracted column.
const char* coln_start = str; const char* coln_start = str;
const char* coln_end = nullptr; const char* coln_end = nullptr;
// The current column. (1-based) // The current column. (1-based)
int colnum = 1; int colnum = 1;
// Whether we are parsing a double-quoted string. // Whether we are parsing a double-quoted string.
bool instring = false; bool instring = false;
// Note that RFC 4180 has strict rules about // Note that RFC 4180 has strict rules about
// double-quotes: ① if a field is double-quoted, the first // double-quotes: ① if a field is double-quoted, the first
// and last characters of the field should be // and last characters of the field should be
// double-quotes; ② if a field contains a double-quote // double-quotes; ② if a field contains a double-quote
// then it should be double quoted, and the occurrences // then it should be double quoted, and the occurrences
// of double-quotes should be doubled. Therefore a CSV file // of double-quotes should be doubled. Therefore a CSV file
// may no contain a line such as: // may no contain a line such as:
// foo,bar"ba""z",12 // foo,bar"ba""z",12
// Tools have different interpretation of such a line. // Tools have different interpretation of such a line.
// For instance Python's pandas.read_csv() function will // For instance Python's pandas.read_csv() function will
// load the second field verbatim as the string 'bar"ba""z"', // load the second field verbatim as the string 'bar"ba""z"',
// while R's read.csv() function will load it as the // while R's read.csv() function will load it as the
// string 'barba"z'. We use this second interpretation, because // string 'barba"z'. We use this second interpretation, because
// it also makes it possible to parse CSVs fields formatted // it also makes it possible to parse CSVs fields formatted
// with leading spaces (often for cosmetic purpose). When // with leading spaces (often for cosmetic purpose). When
// extracting the second field of // extracting the second field of
// foo, "ba""z", 12 // foo, "ba""z", 12
// we will return ' baz' and the leading space will be ignored // we will return ' baz' and the leading space will be ignored
// by our LTL formula parser. // by our LTL formula parser.
while (*str) while (*str)
{ {
switch (*str) switch (*str)
{ {
case '"': case '"':
// Doubled double-quotes are used to escape // Doubled double-quotes are used to escape
// double-quotes. // double-quotes.
if (instring && str[1] == '"') if (instring && str[1] == '"')
++str; ++str;
else else
instring = !instring; instring = !instring;
break; break;
case ',': case ',':
if (!instring) if (!instring)
{ {
if (col_to_read == colnum) if (col_to_read == colnum)
coln_end = str; coln_end = str;
++colnum; ++colnum;
if (col_to_read == colnum) if (col_to_read == colnum)
coln_start = str + 1; coln_start = str + 1;
} }
break; break;
} }
// Once we have the end delimiter for our target // Once we have the end delimiter for our target
// column, we have all we need. // column, we have all we need.
if (coln_end) if (coln_end)
break; break;
++str; ++str;
} }
if (!*str) if (!*str)
{ {
if (colnum != col_to_read) if (colnum != col_to_read)
// Skip this line as it has no enough columns. // Skip this line as it has no enough columns.
continue; continue;
else else
// The target columns ends at the end of the line. // The target columns ends at the end of the line.
coln_end = str; coln_end = str;
} }
// Skip the line if it has an empty field. // Skip the line if it has an empty field.
if (coln_start == coln_end) if (coln_start == coln_end)
continue; continue;
// save the contents before and after that columns for the // save the contents before and after that columns for the
// %< and %> escapes (ignoring the trailing and leading // %< and %> escapes (ignoring the trailing and leading
// commas). // commas).
prefix = (col_to_read != 1) ? prefix = (col_to_read != 1) ?
strndup(col1_start, coln_start - col1_start - 1) : nullptr; strndup(col1_start, coln_start - col1_start - 1) : nullptr;
suffix = (*coln_end != 0) ? strdup(coln_end + 1) : nullptr; suffix = (*coln_end != 0) ? strdup(coln_end + 1) : nullptr;
std::string field(coln_start, coln_end); std::string field(coln_start, coln_end);
// Remove double-quotes if any. // Remove double-quotes if any.
if (field.find('"') != std::string::npos) if (field.find('"') != std::string::npos)
{ {
unsigned dst = 0; unsigned dst = 0;
bool instring = false; bool instring = false;
for (; coln_start != coln_end; ++coln_start) for (; coln_start != coln_end; ++coln_start)
if (*coln_start == '"') if (*coln_start == '"')
// A doubled double-quote instead a double-quoted // A doubled double-quote instead a double-quoted
// string is an escaped double-quote. // string is an escaped double-quote.
if (instring && coln_start[1] == '"') if (instring && coln_start[1] == '"')
field[dst++] = *++coln_start; field[dst++] = *++coln_start;
else else
instring = !instring; instring = !instring;
else else
field[dst++] = *coln_start; field[dst++] = *coln_start;
field.resize(dst); field.resize(dst);
} }
error |= process_string(field, filename, linenum); error |= process_string(field, filename, linenum);
linenum += csvlines; linenum += csvlines;
if (prefix) if (prefix)
{ {
free(prefix); free(prefix);
prefix = nullptr; prefix = nullptr;
} }
if (suffix) if (suffix)
{ {
free(suffix); free(suffix);
suffix = nullptr; suffix = nullptr;
} }
} }
} }
return error; return error;
} }
@ -315,23 +315,23 @@ job_processor::process_file(const char* filename)
long int col = strtol(slash + 1, &end, 10); long int col = strtol(slash + 1, &end, 10);
// strtol ate all remaining characters and NN is positive // strtol ate all remaining characters and NN is positive
if (errno == 0 && !*end && col != 0) if (errno == 0 && !*end && col != 0)
{ {
col_to_read = col; col_to_read = col;
if (real_filename) if (real_filename)
free(real_filename); free(real_filename);
real_filename = strndup(filename, slash - filename); real_filename = strndup(filename, slash - filename);
// Special case for stdin. // Special case for stdin.
if (real_filename[0] == '-' && real_filename[1] == 0) if (real_filename[0] == '-' && real_filename[1] == 0)
return process_stream(std::cin, real_filename); return process_stream(std::cin, real_filename);
std::ifstream input(real_filename); std::ifstream input(real_filename);
if (input) if (input)
return process_stream(input, real_filename); return process_stream(input, real_filename);
error(2, errno, "cannot open '%s' nor '%s'", error(2, errno, "cannot open '%s' nor '%s'",
filename, real_filename); filename, real_filename);
} }
} }
error(2, saved_errno, "cannot open '%s'", filename); error(2, saved_errno, "cannot open '%s'", filename);
@ -345,11 +345,11 @@ job_processor::run()
for (auto& j: jobs) for (auto& j: jobs)
{ {
if (!j.file_p) if (!j.file_p)
error |= process_string(j.str); error |= process_string(j.str);
else else
error |= process_file(j.str); error |= process_file(j.str);
if (abort_run) if (abort_run)
break; break;
} }
return error; return error;
} }

View file

@ -28,7 +28,7 @@
struct job struct job
{ {
const char* str; 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) job(const char* str, bool file_p)
: str(str), file_p(file_p) : str(str), file_p(file_p)
@ -58,11 +58,11 @@ public:
virtual int virtual int
process_formula(spot::formula f, process_formula(spot::formula f,
const char* filename = nullptr, int linenum = 0) = 0; const char* filename = nullptr, int linenum = 0) = 0;
virtual int virtual int
process_string(const std::string& str, process_string(const std::string& str,
const char* filename = nullptr, int linenum = 0); const char* filename = nullptr, int linenum = 0);
virtual int virtual int
process_stream(std::istream& is, const char* filename); process_stream(std::istream& is, const char* filename);

View file

@ -41,8 +41,8 @@ spot::twa_graph_ptr
read_automaton(const char* filename, spot::bdd_dict_ptr& dict) read_automaton(const char* filename, spot::bdd_dict_ptr& dict)
{ {
auto p = spot::parse_aut(filename, dict, auto p = spot::parse_aut(filename, dict,
spot::default_environment::instance(), spot::default_environment::instance(),
opt_parse); opt_parse);
if (p->format_errors(std::cerr)) if (p->format_errors(std::cerr))
error(2, 0, "failed to read automaton from %s", filename); error(2, 0, "failed to read automaton from %s", filename);
if (p->aborted) 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, const struct argp hoaread_argp = { options, parse_opt_hoaread,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr }; nullptr, nullptr };

View file

@ -65,13 +65,13 @@ static const argp_option options[] =
}; };
const struct argp output_argp = { options, parse_opt_output, const struct argp output_argp = { options, parse_opt_output,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr }; nullptr, nullptr };
static static
void void
report_not_ltl(spot::formula f, 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); std::string s = spot::str_psl(f);
static const char msg[] = static const char msg[] =
@ -84,30 +84,30 @@ report_not_ltl(spot::formula f,
std::ostream& std::ostream&
stream_formula(std::ostream& out, stream_formula(std::ostream& out,
spot::formula f, const char* filename, int linenum) spot::formula f, const char* filename, int linenum)
{ {
switch (output_format) switch (output_format)
{ {
case lbt_output: case lbt_output:
if (f.is_ltl_formula()) if (f.is_ltl_formula())
spot::print_lbt_ltl(out, f); spot::print_lbt_ltl(out, f);
else else
report_not_ltl(f, filename, linenum, "LBT"); report_not_ltl(f, filename, linenum, "LBT");
break; break;
case spot_output: case spot_output:
spot::print_psl(out, f, full_parenth); spot::print_psl(out, f, full_parenth);
break; break;
case spin_output: case spin_output:
if (f.is_ltl_formula()) if (f.is_ltl_formula())
spot::print_spin_ltl(out, f, full_parenth); spot::print_spin_ltl(out, f, full_parenth);
else else
report_not_ltl(f, filename, linenum, "Spin"); report_not_ltl(f, filename, linenum, "Spin");
break; break;
case wring_output: case wring_output:
if (f.is_ltl_formula()) if (f.is_ltl_formula())
spot::print_wring_ltl(out, f); spot::print_wring_ltl(out, f);
else else
report_not_ltl(f, filename, linenum, "Wring"); report_not_ltl(f, filename, linenum, "Wring");
break; break;
case utf8_output: case utf8_output:
spot::print_utf8_psl(out, f, full_parenth); spot::print_utf8_psl(out, f, full_parenth);
@ -124,8 +124,8 @@ stream_formula(std::ostream& out,
static void static void
stream_escapable_formula(std::ostream& os, stream_escapable_formula(std::ostream& os,
spot::formula f, spot::formula f,
const char* filename, int linenum) const char* filename, int linenum)
{ {
if (escape_csv) if (escape_csv)
{ {
@ -260,17 +260,17 @@ parse_opt_output(int key, char* arg, struct argp_state*)
static void static void
output_formula(std::ostream& out, output_formula(std::ostream& out,
spot::formula f, spot::formula f,
const char* filename = nullptr, int linenum = 0, const char* filename = nullptr, int linenum = 0,
const char* prefix = nullptr, const char* suffix = nullptr) const char* prefix = nullptr, const char* suffix = nullptr)
{ {
if (!format) if (!format)
{ {
if (prefix) if (prefix)
out << prefix << ','; out << prefix << ',';
stream_escapable_formula(out, f, filename, linenum); stream_escapable_formula(out, f, filename, linenum);
if (suffix) if (suffix)
out << ',' << suffix; out << ',' << suffix;
} }
else else
{ {
@ -287,14 +287,14 @@ void
void void
output_formula_checked(spot::formula f, output_formula_checked(spot::formula f,
const char* filename, int linenum, const char* filename, int linenum,
const char* prefix, const char* suffix) const char* prefix, const char* suffix)
{ {
if (output_format == count_output) if (output_format == count_output)
{ {
if (outputnamer) if (outputnamer)
throw std::runtime_error throw std::runtime_error
("options --output and --count are incompatible"); ("options --output and --count are incompatible");
return; return;
} }
if (output_format == quiet_output) if (output_format == quiet_output)
@ -308,7 +308,7 @@ output_formula_checked(spot::formula f,
std::string fname = outputname.str(); std::string fname = outputname.str();
auto p = outputfiles.emplace(fname, nullptr); auto p = outputfiles.emplace(fname, nullptr);
if (p.second) 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(); out = &p.first->second->ostream();
} }
output_formula(*out, f, filename, linenum, prefix, suffix); output_formula(*out, f, filename, linenum, prefix, suffix);

View file

@ -30,7 +30,7 @@
#include "common_file.hh" #include "common_file.hh"
enum output_format_t { spot_output, spin_output, utf8_output, 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 }; quiet_output, count_output };
extern output_format_t output_format; extern output_format_t output_format;
extern bool full_parenth; extern bool full_parenth;
@ -43,12 +43,12 @@ int parse_opt_output(int key, char* arg, struct argp_state* state);
// Low-level output // Low-level output
std::ostream& std::ostream&
stream_formula(std::ostream& out, 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, void output_formula_checked(spot::formula f,
const char* filename = nullptr, int linenum = 0, const char* filename = nullptr, int linenum = 0,
const char* prefix = nullptr, const char* prefix = nullptr,
const char* suffix = nullptr); const char* suffix = nullptr);
class printable_formula: class printable_formula:
@ -72,15 +72,15 @@ public:
aut_stat_printer(std::ostream& os, const char* format) aut_stat_printer(std::ostream& os, const char* format)
: spot::stat_printer(os, 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; using spot::formater::set_output;
std::ostream& std::ostream&
print(const spot::const_twa_graph_ptr& aut, print(const spot::const_twa_graph_ptr& aut,
spot::formula f = nullptr, spot::formula f = nullptr,
double run_time = -1.) double run_time = -1.)
{ {
formula_ = f; formula_ = f;
return this->spot::stat_printer::print(aut, f, run_time); return this->spot::stat_printer::print(aut, f, run_time);

View file

@ -155,7 +155,7 @@ parse_opt_post(int key, char*, struct argp_state*)
break; break;
case OPT_TGBA: case OPT_TGBA:
if (automaton_format == Spin) if (automaton_format == Spin)
error(2, 0, "--spin and --tgba are incompatible"); error(2, 0, "--spin and --tgba are incompatible");
type = spot::postprocessor::TGBA; type = spot::postprocessor::TGBA;
break; break;
default: default:
@ -165,7 +165,7 @@ parse_opt_post(int key, char*, struct argp_state*)
} }
const struct argp post_argp = { options, parse_opt_post, 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, const struct argp post_argp_disabled = { options_disabled, parse_opt_post,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr }; nullptr, nullptr };

View file

@ -23,7 +23,7 @@
#include <spot/twaalgos/postproc.hh> #include <spot/twaalgos/postproc.hh>
#include <argp.h> #include <argp.h>
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 const struct argp post_argp_disabled; // postprocessing disabled
extern spot::postprocessor::output_type type; extern spot::postprocessor::output_type type;

View file

@ -24,21 +24,21 @@
#define OPT_R 'r' #define OPT_R 'r'
#define DECLARE_OPT_R \ #define DECLARE_OPT_R \
{ "simplify", OPT_R, "LEVEL", OPTION_ARG_OPTIONAL, \ { "simplify", OPT_R, "LEVEL", OPTION_ARG_OPTIONAL, \
"simplify formulas according to LEVEL (see below); LEVEL is " \ "simplify formulas according to LEVEL (see below); LEVEL is " \
"set to 3 if omitted", 0 } "set to 3 if omitted", 0 }
#define LEVEL_DOC(g) \ #define LEVEL_DOC(g) \
{ nullptr, 0, nullptr, 0, \ { nullptr, 0, nullptr, 0, \
"The simplification LEVEL may be set as follows.", g }, \ "The simplification LEVEL may be set as follows.", g }, \
{ " 0", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ { " 0", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
"No rewriting", 0 }, \ "No rewriting", 0 }, \
{ " 1", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ { " 1", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
"basic rewritings and eventual/universal rules", 0 }, \ "basic rewritings and eventual/universal rules", 0 }, \
{ " 2", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ { " 2", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
"additional syntactic implication rules", 0 }, \ "additional syntactic implication rules", 0 }, \
{ " 3", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \ { " 3", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
"better implications using containment", 0 } "better implications using containment", 0 }
extern int simplification_level; extern int simplification_level;

View file

@ -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 // No leading number. It's OK as long as the string is not
// empty. // empty.
if (!*end) if (!*end)
error(1, 0, "invalid empty range"); error(1, 0, "invalid empty range");
res.min = missing_left; res.min = missing_left;
} }
if (!*end) if (!*end)
@ -54,24 +54,24 @@ parse_range(const char* str, int missing_left, int missing_right)
{ {
// Skip : or .. // Skip : or ..
if (end[0] == ':') if (end[0] == ':')
++end; ++end;
else if (end[0] == '.' && end[1] == '.') else if (end[0] == '.' && end[1] == '.')
end += 2; end += 2;
if (!*end && missing_right != 0) if (!*end && missing_right != 0)
{ {
res.max = missing_right; res.max = missing_right;
} }
else else
{ {
// Parse the next integer. // Parse the next integer.
char* end2; char* end2;
res.max = strtol(end, &end2, 10); res.max = strtol(end, &end2, 10);
if (end == end2) if (end == end2)
error(1, 0, "invalid range '%s' (missing end?)", str); error(1, 0, "invalid range '%s' (missing end?)", str);
if (*end2) if (*end2)
error(1, 0, "invalid range '%s' (trailing garbage?)", str); error(1, 0, "invalid range '%s' (trailing garbage?)", str);
} }
} }
if (res.min < 0 || res.max < 0) if (res.min < 0 || res.max < 0)

View file

@ -19,15 +19,15 @@
#pragma once #pragma once
#define RANGE_DOC \ #define RANGE_DOC \
{ nullptr, 0, nullptr, 0, \ { nullptr, 0, nullptr, 0, \
"RANGE may have one of the following forms: 'INT', " \ "RANGE may have one of the following forms: 'INT', " \
"'INT..INT', or '..INT'.\nIn the latter case, the missing number " \ "'INT..INT', or '..INT'.\nIn the latter case, the missing number " \
"is assumed to be 1.", 0 } "is assumed to be 1.", 0 }
#define RANGE_DOC_FULL \ #define RANGE_DOC_FULL \
{ nullptr, 0, nullptr, 0, \ { nullptr, 0, nullptr, 0, \
"RANGE may have one of the following forms: 'INT', " \ "RANGE may have one of the following forms: 'INT', " \
"'INT..INT', '..INT', or 'INT..'", 0 } "'INT..INT', '..INT', or 'INT..'", 0 }
struct range struct range
@ -47,4 +47,4 @@ struct range
// values. Additionally, if missing_right == 0, then the INT.. form // values. Additionally, if missing_right == 0, then the INT.. form
// is disallowed. // is disallowed.
range parse_range(const char* str, range parse_range(const char* str,
int missing_left = 1, int missing_right = 0); int missing_left = 1, int missing_right = 0);

View file

@ -129,7 +129,7 @@ parse_opt_misc(int key, char*, struct argp_state* state)
break; break;
case OPT_USAGE: case OPT_USAGE:
argp_state_help(state, state->out_stream, argp_state_help(state, state->out_stream,
ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
break; break;
case OPT_VERSION: case OPT_VERSION:
display_version(state->out_stream, state); 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, 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, const struct argp misc_argp_hidden = { options_hidden, parse_opt_misc,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr }; nullptr, nullptr };

View file

@ -53,17 +53,17 @@ static void show_shorthands()
{ {
std::cout std::cout
<< ("If a COMMANDFMT does not use any %-sequence, and starts with one of\n" << ("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) for (auto& s: shorthands)
std::cout << " " std::cout << " "
<< std::left << std::setw(12) << s.prefix << std::left << std::setw(12) << s.prefix
<< s.suffix << '\n'; << s.suffix << '\n';
std::cout std::cout
<< ("\nAny {name} and directory component is skipped for the purpose of\n" << ("\nAny {name} and directory component is skipped for the purpose of\n"
"matching those prefixes. So for instance\n" "matching those prefixes. So for instance\n"
" '{DRA} ~/mytools/ltl2dstar-0.5.2'\n" " '{DRA} ~/mytools/ltl2dstar-0.5.2'\n"
"will changed into\n" "will changed into\n"
" '{DRA} ~/mytools/ltl2dstar-0.5.2 --output-format=hoa %L %O'\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; const char* pos = cmd;
unsigned count = 1; unsigned count = 1;
while (*++pos) while (*++pos)
{ {
if (*pos == '{') if (*pos == '{')
++count; ++count;
else if (*pos == '}') else if (*pos == '}')
if (!--count) if (!--count)
{ {
name = strndup(cmd + 1, pos - cmd - 1); name = strndup(cmd + 1, pos - cmd - 1);
cmd = pos + 1; cmd = pos + 1;
while (*cmd == ' ' || *cmd == '\t') while (*cmd == ' ' || *cmd == '\t')
++cmd; ++cmd;
break; break;
} }
} }
} }
// If there is no % in the string, look for a known // If there is no % in the string, look for a known
// command from our shorthand list. If we find it, // command from our shorthand list. If we find it,
@ -100,29 +100,29 @@ translator_spec::translator_spec(const char* spec)
auto basename = cmd; auto basename = cmd;
auto pos = cmd; auto pos = cmd;
while (*pos) while (*pos)
{ {
if (*pos == '/') if (*pos == '/')
basename = pos + 1; basename = pos + 1;
else if (*pos == ' ') else if (*pos == ' ')
break; break;
++pos; ++pos;
} }
// Match a shorthand. // Match a shorthand.
for (auto& p: shorthands) for (auto& p: shorthands)
{ {
int n = strlen(p.prefix); int n = strlen(p.prefix);
if (strncmp(basename, p.prefix, n) == 0) if (strncmp(basename, p.prefix, n) == 0)
{ {
int m = strlen(p.suffix); int m = strlen(p.suffix);
int q = strlen(cmd); int q = strlen(cmd);
char* tmp = static_cast<char*>(malloc(q + m + 1)); char* tmp = static_cast<char*>(malloc(q + m + 1));
strcpy(tmp, cmd); strcpy(tmp, cmd);
strcpy(tmp + q, p.suffix); strcpy(tmp + q, p.suffix);
cmd = tmp; cmd = tmp;
allocated = true; allocated = true;
break; break;
} }
} }
} }
if (!allocated) if (!allocated)
cmd = strdup(cmd); 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, translator_runner::translator_runner(spot::bdd_dict_ptr dict,
bool no_output_allowed) bool no_output_allowed)
: dict(dict) : dict(dict)
{ {
declare('f', &string_ltl_spot); declare('f', &string_ltl_spot);
@ -213,17 +213,17 @@ translator_runner::translator_runner(spot::bdd_dict_ptr dict,
const translator_spec& t = translators[n]; const translator_spec& t = translators[n];
scan(t.cmd, has); scan(t.cmd, has);
if (!(has['f'] || has['s'] || has['l'] || has['w'] if (!(has['f'] || has['s'] || has['l'] || has['w']
|| 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 " error(2, 0, "no input %%-sequence in '%s'.\n Use "
"one of %%f,%%s,%%l,%%w,%%F,%%S,%%L,%%W to indicate how " "one of %%f,%%s,%%l,%%w,%%F,%%S,%%L,%%W to indicate how "
"to pass the formula.", t.spec); "to pass the formula.", t.spec);
if (!no_output_allowed if (!no_output_allowed
&& !(has['O'] || && !(has['O'] ||
// backward-compatibility // backward-compatibility
has['D'] || has['N'] || has['T'] || has['H'])) has['D'] || has['N'] || has['T'] || has['H']))
error(2, 0, "no output %%-sequence in '%s'.\n Use " error(2, 0, "no output %%-sequence in '%s'.\n Use "
"%%O to indicate where the automaton is output.", "%%O to indicate where the automaton is output.",
t.spec); t.spec);
// Remember the %-sequences used by all translators. // Remember the %-sequences used by all translators.
prime(t.cmd); prime(t.cmd);
} }
@ -231,7 +231,7 @@ translator_runner::translator_runner(spot::bdd_dict_ptr dict,
void void
translator_runner::string_to_tmp(std::string& str, unsigned n, translator_runner::string_to_tmp(std::string& str, unsigned n,
std::string& tmpname) std::string& tmpname)
{ {
char prefix[30]; char prefix[30];
snprintf(prefix, sizeof prefix, "lcr-i%u-", n); snprintf(prefix, sizeof prefix, "lcr-i%u-", n);
@ -302,18 +302,18 @@ sig_handler(int sig)
{ {
timed_out = true; timed_out = true;
if (--alarm_on) if (--alarm_on)
{ {
// Send SIGTERM to children. // Send SIGTERM to children.
kill(-child_pid, SIGTERM); kill(-child_pid, SIGTERM);
// Try again later if it didn't work. (alarm() will be reset // Try again later if it didn't work. (alarm() will be reset
// if it did work and the call to wait() returns) // if it did work and the call to wait() returns)
alarm(2); alarm(2);
} }
else else
{ {
// After a few gentle tries, really kill that child. // After a few gentle tries, really kill that child.
kill(-child_pid, SIGKILL); kill(-child_pid, SIGKILL);
} }
} }
else else
{ {
@ -370,7 +370,7 @@ exec_with_timeout(const char* cmd)
alarm_on = 0; alarm_on = 0;
if (w == -1) if (w == -1)
error(2, errno, "error during wait()"); error(2, errno, "error during wait()");
alarm(0); alarm(0);
} }
@ -424,7 +424,7 @@ static int parse_opt_trans(int key, char* arg, struct argp_state*)
timeout = to_pos_int(arg); timeout = to_pos_int(arg);
#if !ENABLE_TIMEOUT #if !ENABLE_TIMEOUT
std::cerr << "warning: setting a timeout is not supported " std::cerr << "warning: setting a timeout is not supported "
<< "on your platform" << std::endl; << "on your platform" << std::endl;
#endif #endif
break; break;
case OPT_LIST: 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, const struct argp trans_argp = { options, parse_opt_trans, nullptr, nullptr,
nullptr, nullptr, nullptr }; nullptr, nullptr, nullptr };

View file

@ -89,9 +89,9 @@ public:
using spot::formater::has; using spot::formater::has;
translator_runner(spot::bdd_dict_ptr dict, translator_runner(spot::bdd_dict_ptr dict,
// whether we accept the absence of output // whether we accept the absence of output
// specifier // specifier
bool no_output_allowed = false); bool no_output_allowed = false);
void string_to_tmp(std::string& str, unsigned n, std::string& tmpname); void string_to_tmp(std::string& str, unsigned n, std::string& tmpname);
const std::string& formula() const; const std::string& formula() const;
void round_formula(spot::formula f, unsigned serial); void round_formula(spot::formula f, unsigned serial);

View file

@ -89,9 +89,9 @@ parse_opt(int key, char* arg, struct argp_state*)
break; break;
case 'x': case 'x':
{ {
const char* opt = extra_options.parse_options(arg); const char* opt = extra_options.parse_options(arg);
if (opt) if (opt)
error(2, 0, "failed to parse --options near '%s'", opt); error(2, 0, "failed to parse --options near '%s'", opt);
} }
break; break;
case ARGP_KEY_ARG: case ARGP_KEY_ARG:
@ -125,7 +125,7 @@ namespace
int int
process_automaton(const spot::const_parsed_aut_ptr& haut, process_automaton(const spot::const_parsed_aut_ptr& haut,
const char* filename) const char* filename)
{ {
spot::stopwatch sw; spot::stopwatch sw;
sw.start(); sw.start();
@ -151,19 +151,19 @@ namespace
auto hp = spot::automaton_stream_parser(filename, opt_parse); auto hp = spot::automaton_stream_parser(filename, opt_parse);
int err = 0; int err = 0;
while (!abort_run) while (!abort_run)
{ {
auto haut = hp.parse(spot::make_bdd_dict()); auto haut = hp.parse(spot::make_bdd_dict());
if (!haut->aut && haut->errors.empty()) if (!haut->aut && haut->errors.empty())
break; break;
if (haut->format_errors(std::cerr)) if (haut->format_errors(std::cerr))
err = 2; err = 2;
if (!haut->aut) if (!haut->aut)
error(2, 0, "failed to read automaton from %s", filename); error(2, 0, "failed to read automaton from %s", filename);
else if (haut->aborted) else if (haut->aborted)
err = std::max(err, aborted(haut, filename)); err = std::max(err, aborted(haut, filename));
else else
process_automaton(haut, filename); process_automaton(haut, filename);
} }
return err; return err;
} }
}; };
@ -175,7 +175,7 @@ main(int argc, char** argv)
setup(argv); setup(argv);
const argp ap = { options, parse_opt, "[FILENAMES...]", 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)) if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
exit(err); exit(err);
@ -192,7 +192,7 @@ main(int argc, char** argv)
{ {
dstar_processor processor(post); dstar_processor processor(post);
if (processor.run()) if (processor.run())
return 2; return 2;
} }
catch (const std::runtime_error& e) catch (const std::runtime_error& e)
{ {

View file

@ -43,8 +43,8 @@
// @InProceedings{gastin.01.cav, // @InProceedings{gastin.01.cav,
// author = {Paul Gastin and Denis Oddoux}, // author = {Paul Gastin and Denis Oddoux},
// title = {Fast {LTL} to {B\"u}chi Automata Translation}, // title = {Fast {LTL} to {B\"u}chi Automata Translation},
// booktitle = {Proceedings of the 13th International Conference on // booktitle = {Proceedings of the 13th International Conference on
// Computer Aided Verification (CAV'01)}, // Computer Aided Verification (CAV'01)},
// pages = {53--65}, // pages = {53--65},
// year = 2001, // year = 2001,
// editor = {G. Berry and H. Comon and A. Finkel}, // editor = {G. Berry and H. Comon and A. Finkel},
@ -58,7 +58,7 @@
// author = {Kristin Y. Rozier and Moshe Y. Vardi}, // author = {Kristin Y. Rozier and Moshe Y. Vardi},
// title = {LTL Satisfiability Checking}, // title = {LTL Satisfiability Checking},
// booktitle = {Proceedings of the 12th International SPIN Workshop on // booktitle = {Proceedings of the 12th International SPIN Workshop on
// Model Checking of Software (SPIN'07)}, // Model Checking of Software (SPIN'07)},
// pages = {149--167}, // pages = {149--167},
// year = {2007}, // year = {2007},
// volume = {4595}, // volume = {4595},
@ -294,9 +294,9 @@ E_n(std::string name, int n)
p << name << n; p << name << n;
formula f = formula::ap(p.str()); formula f = formula::ap(p.str());
if (result) if (result)
result = And_(f, result); result = And_(f, result);
else else
result = f; result = f;
result = F_(result); result = F_(result);
} }
return result; return result;
@ -314,9 +314,9 @@ phi_n(std::string name, int n)
for (; n > 0; --n) for (; n > 0; --n)
{ {
if (result) if (result)
result = And_(p, X_(result)); result = And_(p, X_(result));
else else
result = p; result = p;
} }
return result; return result;
} }
@ -339,14 +339,14 @@ phi_prime_n(std::string name, int n)
for (; n > 0; --n) for (; n > 0; --n)
{ {
if (result) if (result)
{ {
p = X_(p); p = X_(p);
result = And_(result, p); result = And_(result, p);
} }
else else
{ {
result = p; result = p;
} }
} }
return result; return result;
} }
@ -377,9 +377,9 @@ GF_n(std::string name, int n, bool conj = true)
formula f = G_(F_(formula::ap(p.str()))); formula f = G_(F_(formula::ap(p.str())));
if (result) if (result)
result = formula::multop(o, {f, result}); result = formula::multop(o, {f, result});
else else
result = f; result = f;
} }
return result; return result;
} }
@ -403,9 +403,9 @@ FG_n(std::string name, int n, bool conj = false)
formula f = F_(G_(formula::ap(p.str()))); formula f = F_(G_(formula::ap(p.str())));
if (result) if (result)
result = formula::multop(o, {f, result}); result = formula::multop(o, {f, result});
else else
result = f; result = f;
} }
return result; 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); p << name << (right_assoc ? (n + 1 - i) : i);
formula f = formula::ap(p.str()); formula f = formula::ap(p.str());
if (!result) if (!result)
result = f; result = f;
else if (right_assoc) else if (right_assoc)
result = formula::binop(o, f, result); result = formula::binop(o, f, result);
else else
result = formula::binop(o, result, f); result = formula::binop(o, result, f);
} }
return result; return result;
} }
@ -464,9 +464,9 @@ R_n(std::string name, int n)
formula f = Or_(gf, fg); formula f = Or_(gf, fg);
if (result) if (result)
result = And_(f, result); result = And_(f, result);
else else
result = f; result = f;
} }
return result; return result;
} }
@ -501,9 +501,9 @@ Q_n(std::string name, int n)
f = Or_(f, g); f = Or_(f, g);
if (result) if (result)
result = And_(f, result); result = And_(f, result);
else else
result = f; result = f;
} }
return result; 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())); formula f = formula::unop(o, formula::ap(p.str()));
if (result) if (result)
result = formula::multop(cop, {f, result}); result = formula::multop(cop, {f, result});
else else
result = f; result = f;
} }
return result; 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] // G(m -> X(!m)&XX(!m)&XXX(m)) [if n = 3]
std::vector<formula> v(n); std::vector<formula> v(n);
for (int i = 0; i + 1 < n; ++i) 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); v[n - 1] = X_n(m, n);
res[0] = And_(m, G_(Implies_(m, formula::And(std::move(v))))); 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] // G(m -> X(!m & X(!m X(m)))) [if n = 3]
formula p = m; formula p = m;
for (int i = n - 1; i > 0; --i) 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)))); 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] // !b & X(!b) & XX(!b) [if n = 3]
std::vector<formula> v2(n); std::vector<formula> v2(n);
for (int i = 0; i < n; ++i) 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)); res[1] = formula::And(std::move(v2));
} }
else 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] // !b & X(!b & X(!b)) [if n = 3]
formula p = neg_b; formula p = neg_b;
for (int i = n - 1; i > 0; --i) for (int i = n - 1; i > 0; --i)
p = And_(neg_b, X_(p)); p = And_(neg_b, X_(p));
res[1] = 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 Xnm1_b = X_n(b, n - 1);
formula Xn_b = X_(Xnm1_b); formula Xn_b = X_(Xnm1_b);
res[2] = G_(Implies_(And_(m, neg_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 // From the least significant bit to the first 0, all the bits
// are flipped on the next value. Remaining bits are identical. // are flipped on the next value. Remaining bits are identical.
formula Xnm1_negb = X_n(neg_b, n - 1); formula Xnm1_negb = X_n(neg_b, n - 1);
formula Xn_negb = X_(Xnm1_negb); formula Xn_negb = X_(Xnm1_negb);
res[3] = G_(Implies_(And_(m, b), res[3] = G_(Implies_(And_(m, b),
AndX_(Xnm1_negb, AndX_(Xnm1_negb,
U_(And_(And_(b, neg_m), Xn_negb), U_(And_(And_(b, neg_m), Xn_negb),
Or_(m, And_(And_(neg_m, neg_b), Or_(m, And_(And_(neg_m, neg_b),
AndX_(Xnm1_b, AndX_(Xnm1_b,
U_(And_(neg_m, U_(And_(neg_m,
Equiv_(b, Xn_b)), Equiv_(b, Xn_b)),
m)))))))); m))))))));
return formula::And(std::move(res)); return formula::And(std::move(res));
} }
static formula static formula
ltl_counter_carry(std::string bit, std::string marker, 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 b = formula::ap(bit);
formula neg_b = Not_(b); 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] // G(m -> X(!m)&XX(!m)&XXX(m)) [if n = 3]
std::vector<formula> v(n); std::vector<formula> v(n);
for (int i = 0; i + 1 < n; ++i) 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); v[n - 1] = X_n(m, n);
res[0] = And_(m, G_(Implies_(m, formula::And(std::move(v))))); 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] // G(m -> X(!m & X(!m X(m)))) [if n = 3]
formula p = m; formula p = m;
for (int i = n - 1; i > 0; --i) 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)))); 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] // !b & X(!b) & XX(!b) [if n = 3]
std::vector<formula> v2(n); std::vector<formula> v2(n);
for (int i = 0; i < n; ++i) 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)); res[1] = formula::And(std::move(v2));
} }
else else
@ -677,7 +677,7 @@ ltl_counter_carry(std::string bit, std::string marker,
// !b & X(!b & X(!b)) [if n = 3] // !b & X(!b & X(!b)) [if n = 3]
formula p = neg_b; formula p = neg_b;
for (int i = n - 1; i > 0; --i) for (int i = n - 1; i > 0; --i)
p = And_(neg_b, X_(p)); p = And_(neg_b, X_(p));
res[1] = 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. // 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)), 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 // If there's a carry, then add one: flip the bits of b and
// adjust the carry. // adjust the carry.
res[5] = G_(Implies_(c, And_(Implies_(X_(neg_b), res[5] = G_(Implies_(c, And_(Implies_(X_(neg_b),
And_(X_(neg_c), X_(Xn_b))), And_(X_(neg_c), X_(Xn_b))),
Implies_(X_(b), Implies_(X_(b),
And_(X_(c), X_(Xn_negb)))))); And_(X_(c), X_(Xn_negb))))));
} }
else else
{ {
// If there's no carry, then all of the bits stay the same n steps later. // 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)), 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 // If there's a carry, then add one: flip the bits of b and
// adjust the carry. // adjust the carry.
res[5] = G_(Implies_(c, X_(And_(Implies_(neg_b, And_(neg_c, Xn_b)), 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)); return formula::And(std::move(res));
} }
@ -804,12 +804,12 @@ run_jobs()
int inc = (j.range.max < j.range.min) ? -1 : 1; int inc = (j.range.max < j.range.min) ? -1 : 1;
int n = j.range.min; int n = j.range.min;
for (;;) for (;;)
{ {
output_pattern(j.pattern, n); output_pattern(j.pattern, n);
if (n == j.range.max) if (n == j.range.max)
break; break;
n += inc; n += inc;
} }
} }
} }
@ -820,14 +820,14 @@ main(int argc, char** argv)
setup(argv); setup(argv);
const argp ap = { options, parse_opt, nullptr, argp_program_doc, 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)) if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
exit(err); exit(err);
if (jobs.empty()) if (jobs.empty())
error(1, 0, "Nothing to do. Try '%s --help' for more information.", error(1, 0, "Nothing to do. Try '%s --help' for more information.",
program_name); program_name);
run_jobs(); run_jobs();
return 0; return 0;

View file

@ -90,9 +90,9 @@ parse_opt(int key, char* arg, struct argp_state*)
break; break;
case 'x': case 'x':
{ {
const char* opt = extra_options.parse_options(arg); const char* opt = extra_options.parse_options(arg);
if (opt) if (opt)
error(2, 0, "failed to parse --options near '%s'", opt); error(2, 0, "failed to parse --options near '%s'", opt);
} }
break; break;
case ARGP_KEY_ARG: case ARGP_KEY_ARG:
@ -122,19 +122,19 @@ namespace
int int
process_formula(spot::formula f, 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 // This should not happen, because the parser we use can only
// read PSL/LTL formula, but since our formula type can // read PSL/LTL formula, but since our formula type can
// represent more than PSL formula, let's make this // represent more than PSL formula, let's make this
// future-proof. // future-proof.
if (!f.is_psl_formula()) if (!f.is_psl_formula())
{ {
std::string s = spot::str_psl(f); std::string s = spot::str_psl(f);
error_at_line(2, 0, filename, linenum, error_at_line(2, 0, filename, linenum,
"formula '%s' is not an LTL or PSL formula", "formula '%s' is not an LTL or PSL formula",
s.c_str()); s.c_str());
} }
spot::stopwatch sw; spot::stopwatch sw;
sw.start(); sw.start();
@ -142,7 +142,7 @@ namespace
const double translation_time = sw.stop(); const double translation_time = sw.stop();
printer.print(aut, f, filename, linenum, translation_time, nullptr, printer.print(aut, f, filename, linenum, translation_time, nullptr,
prefix, suffix); prefix, suffix);
return 0; return 0;
} }
}; };
@ -157,7 +157,7 @@ main(int argc, char** argv)
setup(argv); setup(argv);
const argp ap = { options, parse_opt, "[FORMULA...]", const argp ap = { options, parse_opt, "[FORMULA...]",
argp_program_doc, children, nullptr, nullptr }; argp_program_doc, children, nullptr, nullptr };
simplification_level = 3; simplification_level = 3;
@ -166,7 +166,7 @@ main(int argc, char** argv)
if (jobs.empty()) if (jobs.empty())
error(2, 0, "No formula to translate? Run '%s --help' for usage.", error(2, 0, "No formula to translate? Run '%s --help' for usage.",
program_name); program_name);
spot::translator trans(&extra_options); spot::translator trans(&extra_options);
trans.set_pref(pref | comp | sbacc | unambig); trans.set_pref(pref | comp | sbacc | unambig);
@ -177,7 +177,7 @@ main(int argc, char** argv)
{ {
trans_processor processor(trans); trans_processor processor(trans);
if (processor.run()) if (processor.run())
return 2; return 2;
} }
catch (const std::runtime_error& e) catch (const std::runtime_error& e)
{ {

View file

@ -119,9 +119,9 @@ parse_opt(int key, char* arg, struct argp_state*)
break; break;
case 'x': case 'x':
{ {
const char* opt = extra_options.parse_options(arg); const char* opt = extra_options.parse_options(arg);
if (opt) if (opt)
error(2, 0, "failed to parse --options near '%s'", opt); error(2, 0, "failed to parse --options near '%s'", opt);
} }
break; break;
case OPT_TGTA: case OPT_TGTA:
@ -171,7 +171,7 @@ namespace
int int
process_formula(spot::formula f, process_formula(spot::formula f,
const char* filename = nullptr, int linenum = 0) const char* filename = nullptr, int linenum = 0)
{ {
auto aut = trans.run(&f); auto aut = trans.run(&f);
@ -180,33 +180,33 @@ namespace
// represent more than PSL formula, let's make this // represent more than PSL formula, let's make this
// future-proof. // future-proof.
if (!f.is_psl_formula()) if (!f.is_psl_formula())
{ {
std::string s = spot::str_psl(f); std::string s = spot::str_psl(f);
error_at_line(2, 0, filename, linenum, error_at_line(2, 0, filename, linenum,
"formula '%s' is not an LTL or PSL formula", "formula '%s' is not an LTL or PSL formula",
s.c_str()); s.c_str());
} }
bdd ap_set = atomic_prop_collect_as_bdd(f, aut); bdd ap_set = atomic_prop_collect_as_bdd(f, aut);
if (ta_type != TGTA) if (ta_type != TGTA)
{ {
auto testing_automaton = auto testing_automaton =
tgba_to_ta(aut, ap_set, type == spot::postprocessor::BA, tgba_to_ta(aut, ap_set, type == spot::postprocessor::BA,
opt_with_artificial_initial_state, opt_with_artificial_initial_state,
opt_single_pass_emptiness_check, opt_single_pass_emptiness_check,
opt_with_artificial_livelock); opt_with_artificial_livelock);
if (level != spot::postprocessor::Low) if (level != spot::postprocessor::Low)
testing_automaton = spot::minimize_ta(testing_automaton); testing_automaton = spot::minimize_ta(testing_automaton);
spot::print_dot(std::cout, testing_automaton); spot::print_dot(std::cout, testing_automaton);
} }
else else
{ {
auto tgta = tgba_to_tgta(aut, ap_set); auto tgta = tgba_to_tgta(aut, ap_set);
if (level != spot::postprocessor::Low) if (level != spot::postprocessor::Low)
tgta = spot::minimize_tgta(tgta); tgta = spot::minimize_tgta(tgta);
spot::print_dot(std::cout, tgta->get_ta()); spot::print_dot(std::cout, tgta->get_ta());
} }
flush_cout(); flush_cout();
return 0; return 0;
} }
@ -219,7 +219,7 @@ main(int argc, char** argv)
setup(argv); setup(argv);
const argp ap = { options, parse_opt, "[FORMULA...]", const argp ap = { options, parse_opt, "[FORMULA...]",
argp_program_doc, children, nullptr, nullptr }; argp_program_doc, children, nullptr, nullptr };
simplification_level = 3; simplification_level = 3;
@ -228,7 +228,7 @@ main(int argc, char** argv)
if (jobs.empty()) if (jobs.empty())
error(2, 0, "No formula to translate? Run '%s --help' for usage.", error(2, 0, "No formula to translate? Run '%s --help' for usage.",
program_name); program_name);
spot::translator trans(&extra_options); spot::translator trans(&extra_options);
trans.set_pref(pref | comp | sbacc); trans.set_pref(pref | comp | sbacc);

File diff suppressed because it is too large Load diff

View file

@ -151,57 +151,57 @@ namespace
spot::twa_graph_ptr res = nullptr; spot::twa_graph_ptr res = nullptr;
if (timed_out) if (timed_out)
{ {
problem = false; // A timeout is considered benign problem = false; // A timeout is considered benign
std::cerr << "warning: timeout during execution of command \"" std::cerr << "warning: timeout during execution of command \""
<< cmd << "\"\n"; << cmd << "\"\n";
++timeout_count; ++timeout_count;
} }
else if (WIFSIGNALED(es)) else if (WIFSIGNALED(es))
{ {
problem = true; problem = true;
es = WTERMSIG(es); es = WTERMSIG(es);
std::cerr << "error: execution of command \"" << cmd std::cerr << "error: execution of command \"" << cmd
<< "\" terminated by signal " << es << ".\n"; << "\" terminated by signal " << es << ".\n";
} }
else if (WIFEXITED(es) && WEXITSTATUS(es) != 0) else if (WIFEXITED(es) && WEXITSTATUS(es) != 0)
{ {
problem = true; problem = true;
es = WEXITSTATUS(es); es = WEXITSTATUS(es);
std::cerr << "error: execution of command \"" << cmd std::cerr << "error: execution of command \"" << cmd
<< "\" returned exit code " << es << ".\n"; << "\" returned exit code " << es << ".\n";
} }
else if (output.val()) else if (output.val())
{ {
problem = false; problem = false;
auto aut = spot::parse_aut(output.val()->name(), dict, auto aut = spot::parse_aut(output.val()->name(), dict,
spot::default_environment::instance(), spot::default_environment::instance(),
opt_parse); opt_parse);
if (!aut->errors.empty()) if (!aut->errors.empty())
{ {
problem = true; problem = true;
std::cerr << "error: failed to parse the automaton " std::cerr << "error: failed to parse the automaton "
"produced by \"" << cmd << "\".\n"; "produced by \"" << cmd << "\".\n";
aut->format_errors(std::cerr); aut->format_errors(std::cerr);
res = nullptr; res = nullptr;
} }
else if (aut->aborted) else if (aut->aborted)
{ {
problem = true; problem = true;
std::cerr << "error: command \"" << cmd std::cerr << "error: command \"" << cmd
<< "\" aborted its output.\n"; << "\" aborted its output.\n";
res = nullptr; res = nullptr;
} }
else else
{ {
res = aut->aut; res = aut->aut;
} }
} }
else // No automaton output else // No automaton output
{ {
problem = false; problem = false;
res = nullptr; res = nullptr;
} }
output.cleanup(); output.cleanup();
return res; return res;
@ -234,18 +234,18 @@ namespace
int int
process_string(const std::string& input, process_string(const std::string& input,
const char* filename, const char* filename,
int linenum) int linenum)
{ {
spot::parsed_formula pf = parse_formula(input); spot::parsed_formula pf = parse_formula(input);
if (!pf.f || !pf.errors.empty()) if (!pf.f || !pf.errors.empty())
{ {
if (filename) 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); pf.format_errors(std::cerr);
return 1; return 1;
} }
inputf = input; inputf = input;
process_formula(pf.f, filename, linenum); process_formula(pf.f, filename, linenum);
@ -255,43 +255,43 @@ namespace
int int
process_formula(spot::formula f, process_formula(spot::formula f,
const char* filename = nullptr, int linenum = 0) const char* filename = nullptr, int linenum = 0)
{ {
std::unique_ptr<spot::relabeling_map> relmap; std::unique_ptr<spot::relabeling_map> relmap;
// If atomic propositions are incompatible with one of the // If atomic propositions are incompatible with one of the
// output, relabel the formula. // output, relabel the formula.
if ((!f.has_lbt_atomic_props() && if ((!f.has_lbt_atomic_props() &&
(runner.has('l') || runner.has('L') || runner.has('T'))) (runner.has('l') || runner.has('L') || runner.has('T')))
|| (!f.has_spin_atomic_props() && || (!f.has_spin_atomic_props() &&
(runner.has('s') || runner.has('S')))) (runner.has('s') || runner.has('S'))))
{ {
relmap.reset(new spot::relabeling_map); relmap.reset(new spot::relabeling_map);
f = spot::relabel(f, spot::Pnn, relmap.get()); f = spot::relabel(f, spot::Pnn, relmap.get());
} }
static unsigned round = 1; static unsigned round = 1;
runner.round_formula(f, round); runner.round_formula(f, round);
unsigned ts = translators.size(); unsigned ts = translators.size();
for (unsigned t = 0; t < ts; ++t) for (unsigned t = 0; t < ts; ++t)
{ {
bool problem; bool problem;
double translation_time; double translation_time;
auto aut = runner.translate(t, problem, translation_time); auto aut = runner.translate(t, problem, translation_time);
if (problem) if (problem)
error_at_line(2, 0, filename, linenum, "aborting here"); error_at_line(2, 0, filename, linenum, "aborting here");
if (aut) if (aut)
{ {
if (relmap) if (relmap)
relabel_here(aut, relmap.get()); relabel_here(aut, relmap.get());
aut = post.run(aut, f); aut = post.run(aut, f);
cmdname = translators[t].name; cmdname = translators[t].name;
roundval = round; roundval = round;
printer.print(aut, f, filename, linenum, translation_time, printer.print(aut, f, filename, linenum, translation_time,
nullptr, prefix, suffix); nullptr, prefix, suffix);
}; };
} }
spot::cleanup_tmpfiles(); spot::cleanup_tmpfiles();
++round; ++round;
return 0; return 0;
@ -305,7 +305,7 @@ main(int argc, char** argv)
setup(argv); setup(argv);
const argp ap = { options, parse_opt, "[COMMANDFMT...]", 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. // Disable post-processing as much as possible by default.
level = spot::postprocessor::Low; level = spot::postprocessor::Low;
@ -319,7 +319,7 @@ main(int argc, char** argv)
if (translators.empty()) if (translators.empty())
error(2, 0, "No translator to run? Run '%s --help' for usage.", error(2, 0, "No translator to run? Run '%s --help' for usage.",
program_name); program_name);
setup_sig_handler(); setup_sig_handler();
@ -332,7 +332,7 @@ main(int argc, char** argv)
{ {
processor p(post); processor p(post);
if (p.run()) if (p.run())
return 2; return 2;
} }
catch (const std::runtime_error& e) catch (const std::runtime_error& e)
{ {

View file

@ -348,10 +348,10 @@ parse_opt(int key, char* arg, struct argp_state*)
break; break;
case OPT_EQUIVALENT_TO: case OPT_EQUIVALENT_TO:
{ {
if (opt->equivalent_to) if (opt->equivalent_to)
error(2, 0, "only one --equivalent-to option can be given"); error(2, 0, "only one --equivalent-to option can be given");
opt->equivalent_to = parse_formula_arg(arg); opt->equivalent_to = parse_formula_arg(arg);
break; break;
} }
case OPT_EXCLUSIVE_AP: case OPT_EXCLUSIVE_AP:
opt->excl_ap.add_group(arg); opt->excl_ap.add_group(arg);
@ -364,17 +364,17 @@ parse_opt(int key, char* arg, struct argp_state*)
break; break;
case OPT_IMPLIED_BY: case OPT_IMPLIED_BY:
{ {
spot::formula i = parse_formula_arg(arg); spot::formula i = parse_formula_arg(arg);
// a→c∧b→c ≡ (ab)→c // a→c∧b→c ≡ (ab)→c
opt->implied_by = spot::formula::Or({opt->implied_by, i}); opt->implied_by = spot::formula::Or({opt->implied_by, i});
break; break;
} }
case OPT_IMPLY: case OPT_IMPLY:
{ {
// a→b∧a→c ≡ a→(b∧c) // a→b∧a→c ≡ a→(b∧c)
spot::formula i = parse_formula_arg(arg); spot::formula i = parse_formula_arg(arg);
opt->imply = spot::formula::And({opt->imply, i}); opt->imply = spot::formula::And({opt->imply, i});
break; break;
} }
case OPT_LTL: case OPT_LTL:
ltl = true; ltl = true;
@ -392,13 +392,13 @@ parse_opt(int key, char* arg, struct argp_state*)
case OPT_RELABEL_BOOL: case OPT_RELABEL_BOOL:
relabeling = (key == OPT_RELABEL_BOOL ? BseRelabeling : ApRelabeling); relabeling = (key == OPT_RELABEL_BOOL ? BseRelabeling : ApRelabeling);
if (!arg || !strncasecmp(arg, "abc", 6)) if (!arg || !strncasecmp(arg, "abc", 6))
style = spot::Abc; style = spot::Abc;
else if (!strncasecmp(arg, "pnn", 4)) else if (!strncasecmp(arg, "pnn", 4))
style = spot::Pnn; style = spot::Pnn;
else else
error(2, 0, "invalid argument for --relabel%s: '%s'", error(2, 0, "invalid argument for --relabel%s: '%s'",
(key == OPT_RELABEL_BOOL ? "-bool" : ""), (key == OPT_RELABEL_BOOL ? "-bool" : ""),
arg); arg);
break; break;
case OPT_REMOVE_WM: case OPT_REMOVE_WM:
unabbreviate += "MW"; unabbreviate += "MW";
@ -426,9 +426,9 @@ parse_opt(int key, char* arg, struct argp_state*)
break; break;
case OPT_UNABBREVIATE: case OPT_UNABBREVIATE:
if (arg) if (arg)
unabbreviate += arg; unabbreviate += arg;
else else
unabbreviate += spot::default_unabbrev_string; unabbreviate += spot::default_unabbrev_string;
break; break;
case OPT_AP_N: case OPT_AP_N:
ap_n = parse_range(arg, 0, std::numeric_limits<int>::max()); ap_n = parse_range(arg, 0, std::numeric_limits<int>::max());
@ -479,87 +479,87 @@ namespace
int int
process_string(const std::string& input, 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); spot::parsed_formula pf = parse_formula(input);
if (!pf.f || !pf.errors.empty()) if (!pf.f || !pf.errors.empty())
{ {
if (!ignore_errors) if (!ignore_errors)
{ {
if (filename) 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); pf.format_errors(std::cerr);
} }
if (error_style == skip_errors) if (error_style == skip_errors)
std::cout << input << '\n'; std::cout << input << '\n';
else else
assert(error_style == drop_errors); assert(error_style == drop_errors);
check_cout(); check_cout();
return !ignore_errors; return !ignore_errors;
} }
try try
{ {
return process_formula(pf.f, filename, linenum); return process_formula(pf.f, filename, linenum);
} }
catch (const std::runtime_error& e) catch (const std::runtime_error& e)
{ {
error_at_line(2, 0, filename, linenum, "%s", e.what()); error_at_line(2, 0, filename, linenum, "%s", e.what());
SPOT_UNREACHABLE(); SPOT_UNREACHABLE();
} }
} }
int int
process_formula(spot::formula f, 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) if (opt_max_count >= 0 && match_count >= opt_max_count)
{ {
abort_run = true; abort_run = true;
return 0; return 0;
} }
if (negate) if (negate)
f = spot::formula::Not(f); f = spot::formula::Not(f);
if (remove_x) if (remove_x)
{ {
// If simplification are enabled, we do them before and after. // If simplification are enabled, we do them before and after.
if (simplification_level) if (simplification_level)
f = simpl.simplify(f); f = simpl.simplify(f);
f = spot::remove_x(f); f = spot::remove_x(f);
} }
if (simplification_level || boolean_to_isop) if (simplification_level || boolean_to_isop)
f = simpl.simplify(f); f = simpl.simplify(f);
if (nnf) if (nnf)
f = simpl.negative_normal_form(f); f = simpl.negative_normal_form(f);
switch (relabeling) switch (relabeling)
{ {
case ApRelabeling: case ApRelabeling:
{ {
relmap.clear(); relmap.clear();
f = spot::relabel(f, style, &relmap); f = spot::relabel(f, style, &relmap);
break; break;
} }
case BseRelabeling: case BseRelabeling:
{ {
relmap.clear(); relmap.clear();
f = spot::relabel_bse(f, style, &relmap); f = spot::relabel_bse(f, style, &relmap);
break; break;
} }
case NoRelabeling: case NoRelabeling:
break; break;
} }
if (!unabbreviate.empty()) if (!unabbreviate.empty())
f = spot::unabbreviate(f, unabbreviate.c_str()); f = spot::unabbreviate(f, unabbreviate.c_str());
if (!opt->excl_ap.empty()) if (!opt->excl_ap.empty())
f = opt->excl_ap.constrain(f); f = opt->excl_ap.constrain(f);
bool matched = true; bool matched = true;
@ -575,32 +575,32 @@ namespace
matched &= !syntactic_persistence || f.is_syntactic_persistence(); matched &= !syntactic_persistence || f.is_syntactic_persistence();
matched &= !syntactic_si || f.is_syntactic_stutter_invariant(); matched &= !syntactic_si || f.is_syntactic_stutter_invariant();
if (matched && (ap_n.min > 0 || ap_n.max >= 0)) if (matched && (ap_n.min > 0 || ap_n.max >= 0))
{ {
auto s = atomic_prop_collect(f); auto s = atomic_prop_collect(f);
int n = s->size(); int n = s->size();
delete s; delete s;
matched &= (ap_n.min <= 0) || (n >= ap_n.min); matched &= (ap_n.min <= 0) || (n >= ap_n.min);
matched &= (ap_n.max < 0) || (n <= ap_n.max); matched &= (ap_n.max < 0) || (n <= ap_n.max);
} }
if (matched && (size.min > 0 || size.max >= 0)) if (matched && (size.min > 0 || size.max >= 0))
{ {
int l = spot::length(f); int l = spot::length(f);
matched &= (size.min <= 0) || (l >= size.min); matched &= (size.min <= 0) || (l >= size.min);
matched &= (size.max < 0) || (l <= size.max); matched &= (size.max < 0) || (l <= size.max);
} }
if (matched && (bsize.min > 0 || bsize.max >= 0)) if (matched && (bsize.min > 0 || bsize.max >= 0))
{ {
int l = spot::length_boolone(f); int l = spot::length_boolone(f);
matched &= (bsize.min <= 0) || (l >= bsize.min); matched &= (bsize.min <= 0) || (l >= bsize.min);
matched &= (bsize.max < 0) || (l <= bsize.max); matched &= (bsize.max < 0) || (l <= bsize.max);
} }
matched &= !opt->implied_by || simpl.implication(opt->implied_by, f); matched &= !opt->implied_by || simpl.implication(opt->implied_by, f);
matched &= !opt->imply || simpl.implication(f, opt->imply); matched &= !opt->imply || simpl.implication(f, opt->imply);
matched &= !opt->equivalent_to 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); matched &= !stutter_insensitive || spot::is_stutter_invariant(f);
// Match obligations and subclasses using WDBA minimization. // Match obligations and subclasses using WDBA minimization.
@ -608,46 +608,46 @@ namespace
// have to compute it on formulas that have been discarded for // have to compute it on formulas that have been discarded for
// other reasons. // other reasons.
if (matched && obligation) if (matched && obligation)
{ {
auto aut = ltl_to_tgba_fm(f, simpl.get_dict()); auto aut = ltl_to_tgba_fm(f, simpl.get_dict());
auto min = minimize_obligation(aut, f); auto min = minimize_obligation(aut, f);
assert(min); assert(min);
if (aut == min) if (aut == min)
{ {
// Not an obligation // Not an obligation
matched = false; matched = false;
} }
else else
{ {
matched &= !guarantee || is_terminal_automaton(min); matched &= !guarantee || is_terminal_automaton(min);
matched &= !safety || is_safety_mwdba(min); matched &= !safety || is_safety_mwdba(min);
} }
} }
matched ^= invert; matched ^= invert;
if (unique && !unique_set.insert(f).second) if (unique && !unique_set.insert(f).second)
matched = false; matched = false;
if (matched) if (matched)
{ {
if (opt->output_define if (opt->output_define
&& output_format != count_output && output_format != count_output
&& output_format != quiet_output) && output_format != quiet_output)
{ {
// Sort the formulas alphabetically. // Sort the formulas alphabetically.
std::map<std::string, spot::formula> m; std::map<std::string, spot::formula> m;
for (auto& p: relmap) for (auto& p: relmap)
m.emplace(str_psl(p.first), p.second); m.emplace(str_psl(p.first), p.second);
for (auto& p: m) for (auto& p: m)
stream_formula(opt->output_define->ostream() stream_formula(opt->output_define->ostream()
<< "#define " << p.first << " (", << "#define " << p.first << " (",
p.second, filename, linenum) << ")\n"; p.second, filename, linenum) << ")\n";
} }
one_match = true; one_match = true;
output_formula_checked(f, filename, linenum, prefix, suffix); output_formula_checked(f, filename, linenum, prefix, suffix);
++match_count; ++match_count;
} }
return 0; return 0;
} }
}; };
@ -659,7 +659,7 @@ main(int argc, char** argv)
setup(argv); setup(argv);
const argp ap = { options, parse_opt, "[FILENAME[/COL]...]", const argp ap = { options, parse_opt, "[FILENAME[/COL]...]",
argp_program_doc, children, nullptr, nullptr }; argp_program_doc, children, nullptr, nullptr };
try try
{ {
@ -669,20 +669,20 @@ main(int argc, char** argv)
opt = &o; opt = &o;
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
exit(err); exit(err);
if (jobs.empty()) if (jobs.empty())
jobs.emplace_back("-", 1); jobs.emplace_back("-", 1);
if (boolean_to_isop && simplification_level == 0) if (boolean_to_isop && simplification_level == 0)
simplification_level = 1; simplification_level = 1;
spot::tl_simplifier_options opt(simplification_level); spot::tl_simplifier_options opt(simplification_level);
opt.boolean_to_isop = boolean_to_isop; opt.boolean_to_isop = boolean_to_isop;
spot::tl_simplifier simpl(opt); spot::tl_simplifier simpl(opt);
ltl_processor processor(simpl); ltl_processor processor(simpl);
if (processor.run()) if (processor.run())
return 2; return 2;
} }
catch (const std::runtime_error& e) catch (const std::runtime_error& e)
{ {

View file

@ -113,12 +113,12 @@ namespace
public: public:
int int
process_formula(spot::formula f, const char* filename = nullptr, process_formula(spot::formula f, const char* filename = nullptr,
int linenum = 0) int linenum = 0)
{ {
auto mutations = 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) for (auto g: mutations)
output_formula_checked(g, filename, linenum, prefix, suffix); output_formula_checked(g, filename, linenum, prefix, suffix);
return 0; return 0;
} }
}; };
@ -182,7 +182,7 @@ main(int argc, char* argv[])
setup(argv); setup(argv);
const argp ap = { options, parse_opt, "[FILENAME[/COL]...]", argp_program_doc, 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)) if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
exit(err); exit(err);

View file

@ -191,24 +191,24 @@ parse_opt(int key, char* arg, struct argp_state* as)
case 'a': case 'a':
opt_acc_prob = to_float(arg); opt_acc_prob = to_float(arg);
if (opt_acc_prob < 0.0 || opt_acc_prob > 1.0) if (opt_acc_prob < 0.0 || opt_acc_prob > 1.0)
error(2, 0, "probability of acceptance set membership " error(2, 0, "probability of acceptance set membership "
"should be between 0.0 and 1.0"); "should be between 0.0 and 1.0");
break; break;
case 'A': case 'A':
if (looks_like_a_range(arg)) if (looks_like_a_range(arg))
{ {
opt_acc_sets = parse_range(arg); opt_acc_sets = parse_range(arg);
if (opt_acc_sets.min > opt_acc_sets.max) if (opt_acc_sets.min > opt_acc_sets.max)
std::swap(opt_acc_sets.min, opt_acc_sets.max); std::swap(opt_acc_sets.min, opt_acc_sets.max);
if (opt_acc_sets.min < 0) if (opt_acc_sets.min < 0)
error(2, 0, "number of acceptance sets should be positive"); error(2, 0, "number of acceptance sets should be positive");
gba_wanted = true; gba_wanted = true;
} }
else else
{ {
opt_acceptance = arg; opt_acceptance = arg;
generic_wanted = true; generic_wanted = true;
} }
break; break;
case 'B': case 'B':
ba_options(); ba_options();
@ -217,7 +217,7 @@ parse_opt(int key, char* arg, struct argp_state* as)
case 'e': case 'e':
opt_density = to_float(arg); opt_density = to_float(arg);
if (opt_density < 0.0 || opt_density > 1.0) 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; break;
case 'D': case 'D':
opt_deterministic = true; opt_deterministic = true;
@ -228,9 +228,9 @@ parse_opt(int key, char* arg, struct argp_state* as)
case 'Q': case 'Q':
opt_states = parse_range(arg); opt_states = parse_range(arg);
if (opt_states.min > opt_states.max) 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) 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; break;
case 'S': case 'S':
opt_state_acc = true; 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 // last non-option argument, and if aprops.empty() we know this
// is the also the first one. // is the also the first one.
if (opt->aprops.empty() if (opt->aprops.empty()
&& as->argc == as->next && looks_like_a_range(arg)) && as->argc == as->next && looks_like_a_range(arg))
{ {
ap_count_given = parse_range(arg); ap_count_given = parse_range(arg);
// Create the set once if the count is fixed. // Create the set once if the count is fixed.
if (ap_count_given.min == ap_count_given.max) if (ap_count_given.min == ap_count_given.max)
opt->aprops = spot::create_atomic_prop_set(ap_count_given.min); opt->aprops = spot::create_atomic_prop_set(ap_count_given.min);
break; break;
} }
opt->aprops.insert(spot::formula::ap(arg)); opt->aprops.insert(spot::formula::ap(arg));
break; break;
@ -281,7 +281,7 @@ main(int argc, char** argv)
setup(argv); setup(argv);
const argp ap = { options, parse_opt, "N|PROP...", argp_program_doc, const argp ap = { options, parse_opt, "N|PROP...", argp_program_doc,
children, nullptr, nullptr }; children, nullptr, nullptr };
try try
{ {
@ -291,43 +291,43 @@ main(int argc, char** argv)
opt = &o; opt = &o;
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) 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 // running 'randaut 0' is one way to generate automata using no
// atomic propositions so do not complain in that case. // atomic propositions so do not complain in that case.
if (opt->aprops.empty() && ap_count_given.max < 0) if (opt->aprops.empty() && ap_count_given.max < 0)
error(2, 0, error(2, 0,
"No atomic proposition supplied? Run '%s --help' for usage.", "No atomic proposition supplied? Run '%s --help' for usage.",
program_name); program_name);
if (generic_wanted && automaton_format == Spin) if (generic_wanted && automaton_format == Spin)
error(2, 0, error(2, 0,
"--spin implies --ba so should not be used with --acceptance"); "--spin implies --ba so should not be used with --acceptance");
if (generic_wanted && ba_wanted) 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) if (automaton_format == Spin && opt_acc_sets.max > 1)
error(2, 0, "--spin is incompatible with --acceptance=%d..%d", error(2, 0, "--spin is incompatible with --acceptance=%d..%d",
opt_acc_sets.min, opt_acc_sets.max); opt_acc_sets.min, opt_acc_sets.max);
if (ba_wanted && opt_acc_sets.min != 1 && opt_acc_sets.max != 1) if (ba_wanted && opt_acc_sets.min != 1 && opt_acc_sets.max != 1)
error(2, 0, "--ba is incompatible with --acceptance=%d..%d", error(2, 0, "--ba is incompatible with --acceptance=%d..%d",
opt_acc_sets.min, opt_acc_sets.max); opt_acc_sets.min, opt_acc_sets.max);
if (ba_wanted && generic_wanted) if (ba_wanted && generic_wanted)
error(2, 0, error(2, 0,
"--ba is incompatible with --acceptance=%s", opt_acceptance); "--ba is incompatible with --acceptance=%s", opt_acceptance);
if (automaton_format == Spin) if (automaton_format == Spin)
ba_options(); ba_options();
if (opt_colored && opt_acc_sets.min == -1 && !generic_wanted) if (opt_colored && opt_acc_sets.min == -1 && !generic_wanted)
error(2, 0, "--colored requires at least one acceptance set; " error(2, 0, "--colored requires at least one acceptance set; "
"use --acceptance"); "use --acceptance");
if (opt_colored && opt_acc_sets.min == 0) if (opt_colored && opt_acc_sets.min == 0)
error(2, 0, "--colored requires at least one acceptance set; " error(2, 0, "--colored requires at least one acceptance set; "
"fix the range of --acceptance"); "fix the range of --acceptance");
if (opt_acc_sets.min == -1) if (opt_acc_sets.min == -1)
opt_acc_sets.min = 0; opt_acc_sets.min = 0;
spot::srand(opt_seed); spot::srand(opt_seed);
auto d = spot::make_bdd_dict(); auto d = spot::make_bdd_dict();
@ -340,70 +340,70 @@ main(int argc, char** argv)
int automaton_num = 0; int automaton_num = 0;
for (;;) for (;;)
{ {
spot::stopwatch sw; spot::stopwatch sw;
sw.start(); sw.start();
if (ap_count_given.max > 0 if (ap_count_given.max > 0
&& ap_count_given.min != ap_count_given.max) && ap_count_given.min != ap_count_given.max)
{ {
int c = spot::rrand(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); opt->aprops = spot::create_atomic_prop_set(c);
} }
int size = opt_states.min; int size = opt_states.min;
if (size != opt_states.max) if (size != opt_states.max)
size = spot::rrand(size, opt_states.max); size = spot::rrand(size, opt_states.max);
int accs = opt_acc_sets.min; int accs = opt_acc_sets.min;
if (accs != opt_acc_sets.max) if (accs != opt_acc_sets.max)
accs = spot::rrand(accs, opt_acc_sets.max); accs = spot::rrand(accs, opt_acc_sets.max);
spot::acc_cond::acc_code code; spot::acc_cond::acc_code code;
if (opt_acceptance) if (opt_acceptance)
{ {
code = spot::acc_cond::acc_code(opt_acceptance); code = spot::acc_cond::acc_code(opt_acceptance);
accs = code.used_sets().max_set(); accs = code.used_sets().max_set();
if (opt_colored && accs == 0) if (opt_colored && accs == 0)
error(2, 0, "--colored requires at least one acceptance set; " error(2, 0, "--colored requires at least one acceptance set; "
"fix the range of --acceptance"); "fix the range of --acceptance");
} }
auto aut = auto aut =
spot::random_graph(size, opt_density, &opt->aprops, d, spot::random_graph(size, opt_density, &opt->aprops, d,
accs, opt_acc_prob, 0.5, accs, opt_acc_prob, 0.5,
opt_deterministic, opt_state_acc, opt_deterministic, opt_state_acc,
opt_colored); opt_colored);
if (opt_acceptance) if (opt_acceptance)
aut->set_acceptance(accs, code); aut->set_acceptance(accs, code);
if (opt_uniq) if (opt_uniq)
{ {
auto tmp = spot::canonicalize auto tmp = spot::canonicalize
(make_twa_graph(aut, spot::twa::prop_set::all())); (make_twa_graph(aut, spot::twa::prop_set::all()));
std::vector<tr_t> trans(tmp->edge_vector().begin() + 1, std::vector<tr_t> trans(tmp->edge_vector().begin() + 1,
tmp->edge_vector().end()); tmp->edge_vector().end());
if (!opt_uniq->emplace(trans).second) if (!opt_uniq->emplace(trans).second)
{ {
--trials; --trials;
if (trials == 0) if (trials == 0)
error(2, 0, "failed to generate a new unique automaton" error(2, 0, "failed to generate a new unique automaton"
" after %d trials", max_trials); " after %d trials", max_trials);
continue; continue;
} }
trials = max_trials; trials = max_trials;
} }
auto runtime = sw.stop(); auto runtime = sw.stop();
printer.print(aut, nullptr, printer.print(aut, nullptr,
opt_seed_str, automaton_num, runtime, nullptr); opt_seed_str, automaton_num, runtime, nullptr);
++automaton_num; ++automaton_num;
if (opt_automata > 0 && automaton_num >= opt_automata) if (opt_automata > 0 && automaton_num >= opt_automata)
break; break;
} }
} }
catch (const std::runtime_error& e) catch (const std::runtime_error& e)
{ {

View file

@ -197,7 +197,7 @@ parse_opt(int key, char* arg, struct argp_state* as)
case OPT_TREE_SIZE: case OPT_TREE_SIZE:
opt_tree_size = parse_range(arg); opt_tree_size = parse_range(arg);
if (opt_tree_size.min > opt_tree_size.max) 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; break;
case OPT_WF: case OPT_WF:
opt_wf = true; 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 // last non-option argument, and if aprops.empty() we know this
// is the also the first one. // is the also the first one.
if (opt->aprops.empty() && as->argc == as->next) if (opt->aprops.empty() && as->argc == as->next)
{ {
char* endptr; char* endptr;
int res = strtol(arg, &endptr, 10); int res = strtol(arg, &endptr, 10);
if (!*endptr && res >= 0) // arg is a number if (!*endptr && res >= 0) // arg is a number
{ {
ap_count_given = true; ap_count_given = true;
opt->aprops = spot::create_atomic_prop_set(res); opt->aprops = spot::create_atomic_prop_set(res);
break; break;
} }
} }
opt->aprops.insert(spot::default_environment::instance().require(arg)); opt->aprops.insert(spot::default_environment::instance().require(arg));
break; break;
default: default:
@ -235,7 +235,7 @@ main(int argc, char** argv)
setup(argv); setup(argv);
const argp ap = { options, parse_opt, "N|PROP...", argp_program_doc, const argp ap = { options, parse_opt, "N|PROP...", argp_program_doc,
children, nullptr, nullptr }; children, nullptr, nullptr };
try try
{ {
@ -245,78 +245,78 @@ main(int argc, char** argv)
opt = &o; opt = &o;
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) 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 // running 'randltl 0' is one way to generate formulas using no
// atomic propositions so do not complain in that case. // atomic propositions so do not complain in that case.
if (opt->aprops.empty() && !ap_count_given) if (opt->aprops.empty() && !ap_count_given)
error(2, 0, "No atomic proposition supplied? " error(2, 0, "No atomic proposition supplied? "
"Run '%s --help' for usage.", program_name); "Run '%s --help' for usage.", program_name);
spot::srand(opt_seed); spot::srand(opt_seed);
spot::randltlgenerator rg spot::randltlgenerator rg
(opt->aprops, (opt->aprops,
[&] (){ [&] (){
spot::option_map opts; spot::option_map opts;
opts.set("output", output); opts.set("output", output);
opts.set("tree_size_min", opt_tree_size.min); opts.set("tree_size_min", opt_tree_size.min);
opts.set("tree_size_max", opt_tree_size.max); opts.set("tree_size_max", opt_tree_size.max);
opts.set("wf", opt_wf); opts.set("wf", opt_wf);
opts.set("seed", opt_seed); opts.set("seed", opt_seed);
opts.set("simplification_level", simplification_level); opts.set("simplification_level", simplification_level);
return opts; return opts;
}(), opt_pL, opt_pS, opt_pB); }(), opt_pL, opt_pS, opt_pB);
if (opt_dump_priorities) if (opt_dump_priorities)
{ {
switch (output) switch (output)
{ {
case OUTPUTLTL: case OUTPUTLTL:
std::cout << std::cout <<
"Use --ltl-priorities to set the following LTL priorities:\n"; "Use --ltl-priorities to set the following LTL priorities:\n";
rg.dump_ltl_priorities(std::cout); rg.dump_ltl_priorities(std::cout);
break; break;
case OUTPUTBOOL: case OUTPUTBOOL:
std::cout << std::cout <<
"Use --boolean-priorities to set the following Boolean " "Use --boolean-priorities to set the following Boolean "
"formula priorities:\n"; "formula priorities:\n";
rg.dump_bool_priorities(std::cout); rg.dump_bool_priorities(std::cout);
break; break;
case OUTPUTPSL: case OUTPUTPSL:
std::cout << std::cout <<
"Use --ltl-priorities to set the following LTL priorities:\n"; "Use --ltl-priorities to set the following LTL priorities:\n";
rg.dump_psl_priorities(std::cout); rg.dump_psl_priorities(std::cout);
// Fall through. // Fall through.
case OUTPUTSERE: case OUTPUTSERE:
std::cout << std::cout <<
"Use --sere-priorities to set the following SERE priorities:\n"; "Use --sere-priorities to set the following SERE priorities:\n";
rg.dump_sere_priorities(std::cout); rg.dump_sere_priorities(std::cout);
std::cout << std::cout <<
"Use --boolean-priorities to set the following Boolean " "Use --boolean-priorities to set the following Boolean "
"formula priorities:\n"; "formula priorities:\n";
rg.dump_sere_bool_priorities(std::cout); rg.dump_sere_bool_priorities(std::cout);
break; break;
default: default:
error(2, 0, "internal error: unknown type of output"); error(2, 0, "internal error: unknown type of output");
} }
exit(0); exit(0);
} }
while (opt_formulas < 0 || opt_formulas--) while (opt_formulas < 0 || opt_formulas--)
{ {
static int count = 0; static int count = 0;
spot::formula f = rg.next(); spot::formula f = rg.next();
if (!f) if (!f)
{ {
error(2, 0, "failed to generate a new unique formula after %d " \ error(2, 0, "failed to generate a new unique formula after %d " \
"trials", MAX_TRIALS); "trials", MAX_TRIALS);
} }
else else
{ {
output_formula_checked(f, nullptr, ++count); output_formula_checked(f, nullptr, ++count);
} }
}; };
} }
catch (const std::runtime_error& e) catch (const std::runtime_error& e)
{ {

View file

@ -113,7 +113,7 @@ Enabled by default.") },
if the TGBA is not already deterministic. Doing so will degeneralize \ if the TGBA is not already deterministic. Doing so will degeneralize \
the automaton. This is disabled by default, unless sat-minimize is set.") }, the automaton. This is disabled by default, unless sat-minimize is set.") },
{ DOC("sat-minimize", { 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 \ 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 \ 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 \ 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 \ to construct a Büchi automaton. Enabling SAT-based minimization will \
also enable tba-det.") }, also enable tba-det.") },
{ DOC("sat-states", { 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 \ 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 \ states. It may however return an automaton with less states if some of \
these are unreachable or useless. Setting sat-states automatically \ 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 could be constructed with the given number of states, the original \
automaton is returned.") }, automaton is returned.") },
{ DOC("sat-acc", { 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. \ attempt to construct a TGBA with the given number of acceptance sets. \
states. It may however return an automaton with less acceptance sets if \ states. It may however return an automaton with less acceptance sets if \
some of these are useless. Setting sat-acc automatically \ some of these are useless. Setting sat-acc automatically \
sets sat-minimize to 1 if not set differently.") }, sets sat-minimize to 1 if not set differently.") },
{ DOC("state-based", { 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 \ 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.") }, sets. By default this is only enabled when option -B is used.") },
{ nullptr, 0, nullptr, 0, nullptr, 0 } { nullptr, 0, nullptr, 0, nullptr, 0 }
@ -155,13 +155,13 @@ main(int argc, char** argv)
setup(argv); setup(argv);
const argp ap = { options, nullptr, nullptr, argp_program_doc, children, 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)) if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
exit(err); exit(err);
std::cerr << "This binary serves no purpose other than generating" std::cerr << "This binary serves no purpose other than generating"
<< " the spot-x.7 manpage.\n"; << " the spot-x.7 manpage.\n";
return 1; return 1;
} }

View file

@ -47,7 +47,7 @@ namespace spot
struct first_is_base_of<Of, Arg1, Args...> struct first_is_base_of<Of, Arg1, Args...>
{ {
static const bool value = static const bool value =
std::is_base_of<Of, typename std::decay<Arg1>::type>::value; std::is_base_of<Of, typename std::decay<Arg1>::type>::value;
}; };
#endif #endif
@ -65,11 +65,11 @@ namespace spot
#ifndef SWIG #ifndef SWIG
template <typename... Args, template <typename... Args,
typename = typename std::enable_if< typename = typename std::enable_if<
!first_is_base_of<boxed_label, Args...>::value>::type> !first_is_base_of<boxed_label, Args...>::value>::type>
boxed_label(Args&&... args) boxed_label(Args&&... args)
noexcept(std::is_nothrow_constructible<Data, Args...>::value) noexcept(std::is_nothrow_constructible<Data, Args...>::value)
: label{std::forward<Args>(args)...} : label{std::forward<Args>(args)...}
{ {
} }
#endif #endif
@ -77,23 +77,23 @@ namespace spot
// if Data is a POD type, G++ 4.8.2 wants default values for all // if Data is a POD type, G++ 4.8.2 wants default values for all
// label fields unless we define this default constructor here. // label fields unless we define this default constructor here.
explicit boxed_label() explicit boxed_label()
noexcept(std::is_nothrow_constructible<Data>::value) noexcept(std::is_nothrow_constructible<Data>::value)
{ {
} }
Data& data() Data& data()
{ {
return label; return label;
} }
const Data& data() const const Data& data() const
{ {
return label; return label;
} }
bool operator<(const boxed_label& other) const 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; typedef std::tuple<> data_t;
std::tuple<>& data() std::tuple<>& data()
{ {
return *this; return *this;
} }
const std::tuple<>& data() const const std::tuple<>& data() const
{ {
return *this; return *this;
} }
}; };
@ -120,11 +120,11 @@ namespace spot
#ifndef SWIG #ifndef SWIG
template <typename... Args, template <typename... Args,
typename = typename std::enable_if< typename = typename std::enable_if<
!first_is_base_of<boxed_label, Args...>::value>::type> !first_is_base_of<boxed_label, Args...>::value>::type>
boxed_label(Args&&... args) boxed_label(Args&&... args)
noexcept(std::is_nothrow_constructible<Data, Args...>::value) noexcept(std::is_nothrow_constructible<Data, Args...>::value)
: Data{std::forward<Args>(args)...} : Data{std::forward<Args>(args)...}
{ {
} }
#endif #endif
@ -132,18 +132,18 @@ namespace spot
// if Data is a POD type, G++ 4.8.2 wants default values for all // if Data is a POD type, G++ 4.8.2 wants default values for all
// label fields unless we define this default constructor here. // label fields unless we define this default constructor here.
explicit boxed_label() explicit boxed_label()
noexcept(std::is_nothrow_constructible<Data>::value) noexcept(std::is_nothrow_constructible<Data>::value)
{ {
} }
Data& data() Data& data()
{ {
return *this; return *this;
} }
const Data& data() const const Data& data() const
{ {
return *this; return *this;
} }
}; };
@ -158,15 +158,15 @@ namespace spot
struct SPOT_API distate_storage final: public State_Data struct SPOT_API distate_storage final: public State_Data
{ {
Edge succ = 0; // First outgoing edge (used when iterating) Edge succ = 0; // First outgoing edge (used when iterating)
Edge succ_tail = 0; // Last outgoing edge (used for Edge succ_tail = 0; // Last outgoing edge (used for
// appending new edges) // appending new edges)
#ifndef SWIG #ifndef SWIG
template <typename... Args, template <typename... Args,
typename = typename std::enable_if< typename = typename std::enable_if<
!first_is_base_of<distate_storage, Args...>::value>::type> !first_is_base_of<distate_storage, Args...>::value>::type>
distate_storage(Args&&... args) distate_storage(Args&&... args)
noexcept(std::is_nothrow_constructible<State_Data, Args...>::value) noexcept(std::is_nothrow_constructible<State_Data, Args...>::value)
: State_Data{std::forward<Args>(args)...} : State_Data{std::forward<Args>(args)...}
{ {
} }
#endif #endif
@ -179,47 +179,47 @@ namespace spot
// Again two implementation: one with label, and one without. // Again two implementation: one with label, and one without.
template <typename StateIn, template <typename StateIn,
typename StateOut, typename Edge, typename Edge_Data> typename StateOut, typename Edge, typename Edge_Data>
struct SPOT_API edge_storage final: public Edge_Data struct SPOT_API edge_storage final: public Edge_Data
{ {
typedef Edge edge; typedef Edge edge;
StateOut dst; // destination StateOut dst; // destination
Edge next_succ; // next outgoing edge with same Edge next_succ; // next outgoing edge with same
// source, or 0 // source, or 0
StateIn src; // source StateIn src; // source
explicit edge_storage() explicit edge_storage()
noexcept(std::is_nothrow_constructible<Edge_Data>::value) noexcept(std::is_nothrow_constructible<Edge_Data>::value)
: Edge_Data{} : Edge_Data{}
{ {
} }
#ifndef SWIG #ifndef SWIG
template <typename... Args> template <typename... Args>
edge_storage(StateOut dst, Edge next_succ, edge_storage(StateOut dst, Edge next_succ,
StateIn src, Args&&... args) StateIn src, Args&&... args)
noexcept(std::is_nothrow_constructible<Edge_Data, Args...>::value noexcept(std::is_nothrow_constructible<Edge_Data, Args...>::value
&& std::is_nothrow_constructible<StateOut, StateOut>::value && std::is_nothrow_constructible<StateOut, StateOut>::value
&& std::is_nothrow_constructible<Edge, Edge>::value) && std::is_nothrow_constructible<Edge, Edge>::value)
: Edge_Data{std::forward<Args>(args)...}, : Edge_Data{std::forward<Args>(args)...},
dst(dst), next_succ(next_succ), src(src) dst(dst), next_succ(next_succ), src(src)
{ {
} }
#endif #endif
bool operator<(const edge_storage& other) const bool operator<(const edge_storage& other) const
{ {
if (src < other.src) if (src < other.src)
return true; return true;
if (src > other.src) if (src > other.src)
return false; return false;
// This might be costly if the destination is a vector // This might be costly if the destination is a vector
if (dst < other.dst) if (dst < other.dst)
return true; return true;
if (dst > other.dst) if (dst > other.dst)
return false; return false;
return this->data() < other.data(); return this->data() < other.data();
} }
bool operator==(const edge_storage& other) const bool operator==(const edge_storage& other) const
@ -241,86 +241,86 @@ namespace spot
template <typename Graph> template <typename Graph>
class SPOT_API edge_iterator: public class SPOT_API edge_iterator: public
std::iterator<std::forward_iterator_tag, std::iterator<std::forward_iterator_tag,
typename typename
std::conditional<std::is_const<Graph>::value, std::conditional<std::is_const<Graph>::value,
const typename Graph::edge_storage_t, const typename Graph::edge_storage_t,
typename Graph::edge_storage_t>::type> typename Graph::edge_storage_t>::type>
{ {
typedef typedef
std::iterator<std::forward_iterator_tag, std::iterator<std::forward_iterator_tag,
typename typename
std::conditional<std::is_const<Graph>::value, std::conditional<std::is_const<Graph>::value,
const typename Graph::edge_storage_t, const typename Graph::edge_storage_t,
typename Graph::edge_storage_t>::type> typename Graph::edge_storage_t>::type>
super; super;
public: public:
typedef typename Graph::edge edge; typedef typename Graph::edge edge;
edge_iterator() noexcept edge_iterator() noexcept
: g_(nullptr), t_(0) : g_(nullptr), t_(0)
{ {
} }
edge_iterator(Graph* g, edge t) noexcept edge_iterator(Graph* g, edge t) noexcept
: g_(g), t_(t) : g_(g), t_(t)
{ {
} }
bool operator==(edge_iterator o) const bool operator==(edge_iterator o) const
{ {
return t_ == o.t_; return t_ == o.t_;
} }
bool operator!=(edge_iterator o) const bool operator!=(edge_iterator o) const
{ {
return t_ != o.t_; return t_ != o.t_;
} }
typename super::reference typename super::reference
operator*() operator*()
{ {
return g_->edge_storage(t_); return g_->edge_storage(t_);
} }
const typename super::reference const typename super::reference
operator*() const operator*() const
{ {
return g_->edge_storage(t_); return g_->edge_storage(t_);
} }
typename super::pointer typename super::pointer
operator->() operator->()
{ {
return &g_->edge_storage(t_); return &g_->edge_storage(t_);
} }
const typename super::pointer const typename super::pointer
operator->() const operator->() const
{ {
return &g_->edge_storage(t_); return &g_->edge_storage(t_);
} }
edge_iterator operator++() edge_iterator operator++()
{ {
t_ = operator*().next_succ; t_ = operator*().next_succ;
return *this; return *this;
} }
edge_iterator operator++(int) edge_iterator operator++(int)
{ {
edge_iterator ti = *this; edge_iterator ti = *this;
t_ = operator*().next_succ; t_ = operator*().next_succ;
return ti; return ti;
} }
operator bool() const operator bool() const
{ {
return t_; return t_;
} }
edge trans() const edge trans() const
{ {
return t_; return t_;
} }
protected: protected:
@ -337,52 +337,52 @@ namespace spot
typedef typename Graph::edge edge; typedef typename Graph::edge edge;
killer_edge_iterator(Graph* g, edge t, state_storage_t& src) noexcept 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++() killer_edge_iterator operator++()
{ {
prev_ = this->t_; prev_ = this->t_;
this->t_ = this->operator*().next_succ; this->t_ = this->operator*().next_succ;
return *this; return *this;
} }
killer_edge_iterator operator++(int) killer_edge_iterator operator++(int)
{ {
killer_edge_iterator ti = *this; killer_edge_iterator ti = *this;
++*this; ++*this;
return ti; return ti;
} }
// Erase the current edge and advance the iterator. // Erase the current edge and advance the iterator.
void erase() void erase()
{ {
edge next = this->operator*().next_succ; edge next = this->operator*().next_succ;
// Update source state and previous edges // Update source state and previous edges
if (prev_) if (prev_)
{ {
this->g_->edge_storage(prev_).next_succ = next; this->g_->edge_storage(prev_).next_succ = next;
} }
else else
{ {
if (src_.succ == this->t_) if (src_.succ == this->t_)
src_.succ = next; src_.succ = next;
} }
if (src_.succ_tail == this->t_) if (src_.succ_tail == this->t_)
{ {
src_.succ_tail = prev_; src_.succ_tail = prev_;
assert(next == 0); assert(next == 0);
} }
// Erased edges have themselves as next_succ. // Erased edges have themselves as next_succ.
this->operator*().next_succ = this->t_; this->operator*().next_succ = this->t_;
// Advance iterator to next edge. // Advance iterator to next edge.
this->t_ = next; this->t_ = next;
++this->g_->killed_edge_; ++this->g_->killed_edge_;
} }
protected: protected:
@ -403,23 +403,23 @@ namespace spot
public: public:
typedef typename Graph::edge edge; typedef typename Graph::edge edge;
state_out(Graph* g, edge t) noexcept state_out(Graph* g, edge t) noexcept
: g_(g), t_(t) : g_(g), t_(t)
{ {
} }
edge_iterator<Graph> begin() edge_iterator<Graph> begin()
{ {
return {g_, t_}; return {g_, t_};
} }
edge_iterator<Graph> end() edge_iterator<Graph> end()
{ {
return {}; return {};
} }
void recycle(edge t) void recycle(edge t)
{ {
t_ = t; t_ = t;
} }
protected: protected:
@ -434,92 +434,92 @@ namespace spot
template <typename Graph> template <typename Graph>
class SPOT_API all_edge_iterator: public class SPOT_API all_edge_iterator: public
std::iterator<std::forward_iterator_tag, std::iterator<std::forward_iterator_tag,
typename typename
std::conditional<std::is_const<Graph>::value, std::conditional<std::is_const<Graph>::value,
const typename Graph::edge_storage_t, const typename Graph::edge_storage_t,
typename Graph::edge_storage_t>::type> typename Graph::edge_storage_t>::type>
{ {
typedef typedef
std::iterator<std::forward_iterator_tag, std::iterator<std::forward_iterator_tag,
typename typename
std::conditional<std::is_const<Graph>::value, std::conditional<std::is_const<Graph>::value,
const typename Graph::edge_storage_t, const typename Graph::edge_storage_t,
typename Graph::edge_storage_t>::type> typename Graph::edge_storage_t>::type>
super; super;
typedef typename std::conditional<std::is_const<Graph>::value, typedef typename std::conditional<std::is_const<Graph>::value,
const typename Graph::edge_vector_t, const typename Graph::edge_vector_t,
typename Graph::edge_vector_t>::type typename Graph::edge_vector_t>::type
tv_t; tv_t;
unsigned t_; unsigned t_;
tv_t& tv_; tv_t& tv_;
void skip_() void skip_()
{ {
unsigned s = tv_.size(); unsigned s = tv_.size();
do do
++t_; ++t_;
while (t_ < s && tv_[t_].next_succ == t_); while (t_ < s && tv_[t_].next_succ == t_);
} }
public: public:
all_edge_iterator(unsigned pos, tv_t& tv) noexcept 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 all_edge_iterator(tv_t& tv) noexcept
: t_(tv.size()), tv_(tv) : t_(tv.size()), tv_(tv)
{ {
} }
all_edge_iterator& operator++() all_edge_iterator& operator++()
{ {
skip_(); skip_();
return *this; return *this;
} }
all_edge_iterator operator++(int) all_edge_iterator operator++(int)
{ {
all_edge_iterator old = *this; all_edge_iterator old = *this;
++*this; ++*this;
return old; return old;
} }
bool operator==(all_edge_iterator o) const bool operator==(all_edge_iterator o) const
{ {
return t_ == o.t_; return t_ == o.t_;
} }
bool operator!=(all_edge_iterator o) const bool operator!=(all_edge_iterator o) const
{ {
return t_ != o.t_; return t_ != o.t_;
} }
typename super::reference typename super::reference
operator*() operator*()
{ {
return tv_[t_]; return tv_[t_];
} }
const typename super::reference const typename super::reference
operator*() const operator*() const
{ {
return tv_[t_]; return tv_[t_];
} }
const typename super::pointer const typename super::pointer
operator->() operator->()
{ {
return &tv_[t_]; return &tv_[t_];
} }
typename super::pointer typename super::pointer
operator->() const operator->() const
{ {
return &tv_[t_]; return &tv_[t_];
} }
}; };
@ -529,27 +529,27 @@ namespace spot
{ {
public: public:
typedef typename std::conditional<std::is_const<Graph>::value, typedef typename std::conditional<std::is_const<Graph>::value,
const typename Graph::edge_vector_t, const typename Graph::edge_vector_t,
typename Graph::edge_vector_t>::type typename Graph::edge_vector_t>::type
tv_t; tv_t;
typedef all_edge_iterator<Graph> iter_t; typedef all_edge_iterator<Graph> iter_t;
private: private:
tv_t& tv_; tv_t& tv_;
public: public:
all_trans(tv_t& tv) noexcept all_trans(tv_t& tv) noexcept
: tv_(tv) : tv_(tv)
{ {
} }
iter_t begin() iter_t begin()
{ {
return {0, tv_}; return {0, tv_};
} }
iter_t end() iter_t end()
{ {
return {tv_}; return {tv_};
} }
}; };
@ -586,14 +586,14 @@ namespace spot
// The type of an output state (when seen from a edge) // The type of an output state (when seen from a edge)
// depends on the kind of graph we build // depends on the kind of graph we build
typedef typename std::conditional<Alternating, typedef typename std::conditional<Alternating,
std::vector<state>, std::vector<state>,
state>::type out_state; state>::type out_state;
typedef internal::distate_storage<edge, typedef internal::distate_storage<edge,
internal::boxed_label<State_Data>> internal::boxed_label<State_Data>>
state_storage_t; state_storage_t;
typedef internal::edge_storage<state, out_state, edge, typedef internal::edge_storage<state, out_state, edge,
internal::boxed_label<Edge_Data>> internal::boxed_label<Edge_Data>>
edge_storage_t; edge_storage_t;
typedef std::vector<state_storage_t> state_vector; typedef std::vector<state_storage_t> state_vector;
typedef std::vector<edge_storage_t> edge_vector_t; typedef std::vector<edge_storage_t> edge_vector_t;
@ -614,7 +614,7 @@ namespace spot
{ {
states_.reserve(max_states); states_.reserve(max_states);
if (max_trans == 0) if (max_trans == 0)
max_trans = max_states * 2; max_trans = max_states * 2;
edges_.reserve(max_trans + 1); edges_.reserve(max_trans + 1);
// Edge number 0 is not used, because we use this index // Edge number 0 is not used, because we use this index
// to mark the absence of a edge. // to mark the absence of a edge.
@ -638,7 +638,7 @@ namespace spot
// Erased edges have their next_succ pointing to // Erased edges have their next_succ pointing to
// themselves. // themselves.
return (t < edges_.size() && return (t < edges_.size() &&
edges_[t].next_succ != t); edges_[t].next_succ != t);
} }
template <typename... Args> template <typename... Args>
@ -655,7 +655,7 @@ namespace spot
state s = states_.size(); state s = states_.size();
states_.reserve(s + n); states_.reserve(s + n);
while (n--) while (n--)
states_.emplace_back(std::forward<Args>(args)...); states_.emplace_back(std::forward<Args>(args)...);
return s; return s;
} }
@ -730,9 +730,9 @@ namespace spot
edge st = states_[src].succ_tail; edge st = states_[src].succ_tail;
assert(st < t || !st); assert(st < t || !st);
if (!st) if (!st)
states_[src].succ = t; states_[src].succ = t;
else else
edges_[st].next_succ = t; edges_[st].next_succ = t;
states_[src].succ_tail = t; states_[src].succ_tail = t;
return t; return t;
} }
@ -836,19 +836,19 @@ namespace spot
{ {
unsigned tend = edges_.size(); unsigned tend = edges_.size();
for (unsigned t = 1; t < tend; ++t) for (unsigned t = 1; t < tend; ++t)
{ {
o << 't' << t << ": (s" o << 't' << t << ": (s"
<< edges_[t].src << ", s" << edges_[t].src << ", s"
<< edges_[t].dst << ") t" << edges_[t].dst << ") t"
<< edges_[t].next_succ << '\n'; << edges_[t].next_succ << '\n';
} }
unsigned send = states_.size(); unsigned send = states_.size();
for (unsigned s = 0; s < send; ++s) for (unsigned s = 0; s < send; ++s)
{ {
o << 's' << s << ": t" o << 's' << s << ": t"
<< states_[s].succ << " t" << states_[s].succ << " t"
<< states_[s].succ_tail << '\n'; << states_[s].succ_tail << '\n';
} }
} }
// Remove all dead edges. The edges_ vector is left // Remove all dead edges. The edges_ vector is left
@ -858,11 +858,11 @@ namespace spot
void remove_dead_edges_() void remove_dead_edges_()
{ {
if (killed_edge_ == 0) if (killed_edge_ == 0)
return; return;
auto i = std::remove_if(edges_.begin() + 1, edges_.end(), auto i = std::remove_if(edges_.begin() + 1, edges_.end(),
[this](const edge_storage_t& t) { [this](const edge_storage_t& t) {
return this->is_dead_edge(t); return this->is_dead_edge(t);
}); });
edges_.erase(i, edges_.end()); edges_.erase(i, edges_.end());
killed_edge_ = 0; killed_edge_ = 0;
} }
@ -885,38 +885,38 @@ namespace spot
state last_src = -1U; state last_src = -1U;
edge tend = edges_.size(); edge tend = edges_.size();
for (edge t = 1; t < tend; ++t) for (edge t = 1; t < tend; ++t)
{ {
state src = edges_[t].src; state src = edges_[t].src;
if (src != last_src) if (src != last_src)
{ {
states_[src].succ = t; states_[src].succ = t;
if (last_src != -1U) if (last_src != -1U)
{ {
states_[last_src].succ_tail = t - 1; states_[last_src].succ_tail = t - 1;
edges_[t - 1].next_succ = 0; edges_[t - 1].next_succ = 0;
} }
while (++last_src != src) while (++last_src != src)
{ {
states_[last_src].succ = 0; states_[last_src].succ = 0;
states_[last_src].succ_tail = 0; states_[last_src].succ_tail = 0;
} }
} }
else else
{ {
edges_[t - 1].next_succ = t; edges_[t - 1].next_succ = t;
} }
} }
if (last_src != -1U) if (last_src != -1U)
{ {
states_[last_src].succ_tail = tend - 1; states_[last_src].succ_tail = tend - 1;
edges_[tend - 1].next_succ = 0; edges_[tend - 1].next_succ = 0;
} }
unsigned send = states_.size(); unsigned send = states_.size();
while (++last_src != send) while (++last_src != send)
{ {
states_[last_src].succ = 0; states_[last_src].succ = 0;
states_[last_src].succ_tail = 0; states_[last_src].succ_tail = 0;
} }
//std::cerr << "\nafter\n"; //std::cerr << "\nafter\n";
//dump_storage(std::cerr); //dump_storage(std::cerr);
} }
@ -930,10 +930,10 @@ namespace spot
assert(newst.size() == states_.size()); assert(newst.size() == states_.size());
unsigned tend = edges_.size(); unsigned tend = edges_.size();
for (unsigned t = 1; t < tend; t++) for (unsigned t = 1; t < tend; t++)
{ {
edges_[t].dst = newst[edges_[t].dst]; edges_[t].dst = newst[edges_[t].dst];
edges_[t].src = newst[edges_[t].src]; edges_[t].src = newst[edges_[t].src];
} }
} }
void defrag_states(std::vector<unsigned>&& newst, unsigned used_states) void defrag_states(std::vector<unsigned>&& newst, unsigned used_states)
@ -947,22 +947,22 @@ namespace spot
// Shift all states in states_, as indicated by newst. // Shift all states in states_, as indicated by newst.
unsigned send = states_.size(); unsigned send = states_.size();
for (state s = 0; s < send; ++s) for (state s = 0; s < send; ++s)
{ {
state dst = newst[s]; state dst = newst[s];
if (dst == s) if (dst == s)
continue; continue;
if (dst == -1U) if (dst == -1U)
{ {
// This is an erased state. Mark all its edges as // This is an erased state. Mark all its edges as
// dead (i.e., t.next_succ should point to t for each of // dead (i.e., t.next_succ should point to t for each of
// them). // them).
auto t = states_[s].succ; auto t = states_[s].succ;
while (t) while (t)
std::swap(t, edges_[t].next_succ); std::swap(t, edges_[t].next_succ);
continue; continue;
} }
states_[dst] = std::move(states_[s]); states_[dst] = std::move(states_[s]);
} }
states_.resize(used_states); states_.resize(used_states);
// Shift all edges in edges_. The algorithm is // Shift all edges in edges_. The algorithm is
@ -972,33 +972,33 @@ namespace spot
std::vector<edge> newidx(tend); std::vector<edge> newidx(tend);
unsigned dest = 1; unsigned dest = 1;
for (edge t = 1; t < tend; ++t) for (edge t = 1; t < tend; ++t)
{ {
if (is_dead_edge(t)) if (is_dead_edge(t))
continue; continue;
if (t != dest) if (t != dest)
edges_[dest] = std::move(edges_[t]); edges_[dest] = std::move(edges_[t]);
newidx[t] = dest; newidx[t] = dest;
++dest; ++dest;
} }
edges_.resize(dest); edges_.resize(dest);
killed_edge_ = 0; killed_edge_ = 0;
// Adjust next_succ and dst pointers in all edges. // Adjust next_succ and dst pointers in all edges.
for (edge t = 1; t < dest; ++t) for (edge t = 1; t < dest; ++t)
{ {
auto& tr = edges_[t]; auto& tr = edges_[t];
tr.next_succ = newidx[tr.next_succ]; tr.next_succ = newidx[tr.next_succ];
tr.dst = newst[tr.dst]; tr.dst = newst[tr.dst];
tr.src = newst[tr.src]; tr.src = newst[tr.src];
assert(tr.dst != -1U); assert(tr.dst != -1U);
} }
// Adjust succ and succ_tails pointers in all states. // Adjust succ and succ_tails pointers in all states.
for (auto& s: states_) for (auto& s: states_)
{ {
s.succ = newidx[s.succ]; s.succ = newidx[s.succ];
s.succ_tail = newidx[s.succ_tail]; s.succ_tail = newidx[s.succ_tail];
} }
//std::cerr << "\nafter defrag\n"; //std::cerr << "\nafter defrag\n";
//dump_storage(std::cerr); //dump_storage(std::cerr);

View file

@ -26,9 +26,9 @@
namespace spot namespace spot
{ {
template <typename Graph, template <typename Graph,
typename State_Name, typename State_Name,
typename Name_Hash = std::hash<State_Name>, typename Name_Hash = std::hash<State_Name>,
typename Name_Equal = std::equal_to<State_Name>> typename Name_Equal = std::equal_to<State_Name>>
class SPOT_API named_graph class SPOT_API named_graph
{ {
protected: protected:
@ -40,7 +40,7 @@ namespace spot
typedef State_Name name; typedef State_Name name;
typedef std::unordered_map<name, state, typedef std::unordered_map<name, state,
Name_Hash, Name_Equal> name_to_state_t; Name_Hash, Name_Equal> name_to_state_t;
name_to_state_t name_to_state; name_to_state_t name_to_state;
typedef std::vector<name> state_to_name_t; typedef std::vector<name> state_to_name_t;
state_to_name_t state_to_name; state_to_name_t state_to_name;
@ -65,14 +65,14 @@ namespace spot
{ {
auto p = name_to_state.emplace(n, 0U); auto p = name_to_state.emplace(n, 0U);
if (p.second) if (p.second)
{ {
unsigned s = g_.new_state(std::forward<Args>(args)...); unsigned s = g_.new_state(std::forward<Args>(args)...);
p.first->second = s; p.first->second = s;
if (state_to_name.size() < s + 1) if (state_to_name.size() < s + 1)
state_to_name.resize(s + 1); state_to_name.resize(s + 1);
state_to_name[s] = n; state_to_name[s] = n;
return s; return s;
} }
return p.first->second; return p.first->second;
} }
@ -85,27 +85,27 @@ namespace spot
{ {
auto p = name_to_state.emplace(newname, s); auto p = name_to_state.emplace(newname, s);
if (!p.second) if (!p.second)
{ {
// The state already exists. Change its number. // The state already exists. Change its number.
auto old = p.first->second; auto old = p.first->second;
p.first->second = s; p.first->second = s;
// Add the successor of OLD to those of S. // Add the successor of OLD to those of S.
auto& trans = g_.edge_vector(); auto& trans = g_.edge_vector();
auto& states = g_.states(); auto& states = g_.states();
trans[states[s].succ_tail].next_succ = states[old].succ; trans[states[s].succ_tail].next_succ = states[old].succ;
states[s].succ_tail = states[old].succ_tail; states[s].succ_tail = states[old].succ_tail;
states[old].succ = 0; states[old].succ = 0;
states[old].succ_tail = 0; states[old].succ_tail = 0;
// Remove all references to old in edges: // Remove all references to old in edges:
unsigned tend = trans.size(); unsigned tend = trans.size();
for (unsigned t = 1; t < tend; ++t) for (unsigned t = 1; t < tend; ++t)
{ {
if (trans[t].src == old) if (trans[t].src == old)
trans[t].src = s; trans[t].src = s;
if (trans[t].dst == old) if (trans[t].dst == old)
trans[t].dst = s; trans[t].dst = s;
} }
} }
return !p.second; return !p.second;
} }
@ -134,7 +134,7 @@ namespace spot
new_edge(name src, name dst, Args&&... args) new_edge(name src, name dst, Args&&... args)
{ {
return g_.new_edge(get_state(src), get_state(dst), return g_.new_edge(get_state(src), get_state(dst),
std::forward<Args>(args)...); std::forward<Args>(args)...);
} }
template <typename... Args> template <typename... Args>
@ -144,19 +144,19 @@ namespace spot
std::vector<State_Name> d; std::vector<State_Name> d;
d.reserve(dst.size()); d.reserve(dst.size());
for (auto n: dst) 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>(args)...); return g_.new_edge(get_state(src), d, std::forward<Args>(args)...);
} }
template <typename... Args> template <typename... Args>
edge edge
new_edge(name src, new_edge(name src,
const std::initializer_list<State_Name>& dst, Args&&... args) const std::initializer_list<State_Name>& dst, Args&&... args)
{ {
std::vector<state> d; std::vector<state> d;
d.reserve(dst.size()); d.reserve(dst.size());
for (auto n: dst) 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>(args)...); return g_.new_edge(get_state(src), d, std::forward<Args>(args)...);
} }
}; };

View file

@ -46,16 +46,16 @@ namespace spot
// Do not simply return "other - this", it might not fit in an int. // Do not simply return "other - this", it might not fit in an int.
if (o < this) if (o < this)
return -1; return -1;
if (o > this) if (o > this)
return 1; return 1;
return 0; return 0;
} }
virtual size_t hash() const override virtual size_t hash() const override
{ {
return return
reinterpret_cast<const char*>(this) - static_cast<const char*>(nullptr); reinterpret_cast<const char*>(this) - static_cast<const char*>(nullptr);
} }
virtual kripke_graph_state* virtual kripke_graph_state*
@ -93,7 +93,7 @@ namespace spot
edge p_; edge p_;
public: public:
kripke_graph_succ_iterator(const Graph* g, 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()), kripke_succ_iterator(s->cond()),
g_(g), g_(g),
t_(s->succ) t_(s->succ)
@ -131,7 +131,7 @@ namespace spot
{ {
assert(!done()); assert(!done());
return const_cast<kripke_graph_state*> return const_cast<kripke_graph_state*>
(&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 graph_t::state get_init_state_number() const
{ {
if (num_states() == 0) if (num_states() == 0)
const_cast<graph_t&>(g_).new_state(); const_cast<graph_t&>(g_).new_state();
return init_number_; return init_number_;
} }
virtual const kripke_graph_state* get_init_state() const override virtual const kripke_graph_state* get_init_state() const override
{ {
if (num_states() == 0) if (num_states() == 0)
const_cast<graph_t&>(g_).new_state(); const_cast<graph_t&>(g_).new_state();
return state_from_number(init_number_); return state_from_number(init_number_);
} }
@ -197,13 +197,13 @@ namespace spot
assert(!s->succ || g_.valid_trans(s->succ)); assert(!s->succ || g_.valid_trans(s->succ));
if (this->iter_cache_) if (this->iter_cache_)
{ {
auto it = auto it =
down_cast<kripke_graph_succ_iterator<graph_t>*>(this->iter_cache_); down_cast<kripke_graph_succ_iterator<graph_t>*>(this->iter_cache_);
it->recycle(s); it->recycle(s);
this->iter_cache_ = nullptr; this->iter_cache_ = nullptr;
return it; return it;
} }
return new kripke_graph_succ_iterator<graph_t>(&g_, s); return new kripke_graph_succ_iterator<graph_t>(&g_, s);
} }

File diff suppressed because it is too large Load diff

View file

@ -67,9 +67,9 @@ namespace spot
// to enable compression, 2 to enable a faster compression that only // to enable compression, 2 to enable a faster compression that only
// work if all variables are smaller than 2^28. // work if all variables are smaller than 2^28.
kripke_ptr kripke(const atomic_prop_set* to_observe, kripke_ptr kripke(const atomic_prop_set* to_observe,
bdd_dict_ptr dict, bdd_dict_ptr dict,
formula dead = formula::tt(), formula dead = formula::tt(),
int compress = 0) const; int compress = 0) const;
/// Number of variables in a state /// Number of variables in a state
int state_size() const; int state_size() const;

View file

@ -32,12 +32,12 @@ namespace spot
{ {
// Bare words cannot be empty and should start with a letter. // Bare words cannot be empty and should start with a letter.
if (!*str if (!*str
|| !(isalpha(*str) || *str == '_' || *str == '.')) || !(isalpha(*str) || *str == '_' || *str == '.'))
return false; return false;
// The remaining of the word must be alphanumeric. // The remaining of the word must be alphanumeric.
while (*++str) while (*++str)
if (!(isalnum(*str) || *str == '_' || *str == '.')) if (!(isalnum(*str) || *str == '_' || *str == '.'))
return false; return false;
return true; return true;
} }
@ -58,7 +58,7 @@ namespace spot
return false; return false;
while (*++str) while (*++str)
if (!(isalnum(*str) || *str == '_')) if (!(isalnum(*str) || *str == '_'))
return false; return false;
return true; return true;
} }

View file

@ -39,7 +39,7 @@ namespace spot
const size_t bpb = 8 * sizeof(bitvect::block_t); const size_t bpb = 8 * sizeof(bitvect::block_t);
size_t n = (bitcount + bpb - 1) / bpb; size_t n = (bitcount + bpb - 1) / bpb;
if (n < 1) if (n < 1)
return 1; return 1;
return n; return n;
} }
@ -60,12 +60,12 @@ namespace spot
{ {
static unsigned long init() static unsigned long init()
{ {
return 14695981039346656037UL; return 14695981039346656037UL;
} }
static unsigned long prime() static unsigned long prime()
{ {
return 1099511628211UL; return 1099511628211UL;
} }
}; };
#endif #endif
@ -76,12 +76,12 @@ namespace spot
{ {
static unsigned long init() static unsigned long init()
{ {
return 2166136261UL; return 2166136261UL;
} }
static unsigned long prime() static unsigned long prime()
{ {
return 16777619UL; return 16777619UL;
} }
}; };
@ -109,7 +109,7 @@ namespace spot
// already contains one int of local_storage_, but // already contains one int of local_storage_, but
// we allocate n-1 more so that we store the table. // we allocate n-1 more so that we store the table.
void* mem = operator new(sizeof(bitvect) 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); bitvect* res = new(mem) bitvect(size_, n, true);
memcpy(res->storage_, storage_, res->block_count_ * sizeof(block_t)); memcpy(res->storage_, storage_, res->block_count_ * sizeof(block_t));
return res; return res;
@ -125,8 +125,8 @@ namespace spot
return res; return res;
for (i = 0; i < m - 1; ++i) for (i = 0; i < m - 1; ++i)
{ {
res ^= storage_[i]; res ^= storage_[i];
res *= fnv<sizeof(block_t)>::prime(); res *= fnv<sizeof(block_t)>::prime();
} }
// Deal with the last block, that might not be fully used. // Deal with the last block, that might not be fully used.
// Compute the number n of bits used in the last block. // 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 // already contains one int of local_storage_, but
// we allocate n-1 more so that we store the table. // we allocate n-1 more so that we store the table.
void* mem = operator new(sizeof(bitvect) void* mem = operator new(sizeof(bitvect)
+ (n - 1) * sizeof(bitvect::block_t)); + (n - 1) * sizeof(bitvect::block_t));
return new(mem) bitvect(bitcount, n); return new(mem) bitvect(bitcount, n);
} }
@ -176,16 +176,16 @@ namespace spot
size_t end = a.size(); size_t end = a.size();
if (end == 0) if (end == 0)
{ {
os << "empty\n"; os << "empty\n";
return os; return os;
} }
int w = floor(log10(end - 1)) + 1; int w = floor(log10(end - 1)) + 1;
for (size_t i = 0; i != end; ++i) for (size_t i = 0; i != end; ++i)
{ {
os.width(w); os.width(w);
os << i; os << i;
os.width(1); os.width(1);
os << ": " << a.at(i) << '\n'; os << ": " << a.at(i) << '\n';
} }
return os; return os;
} }

View file

@ -44,7 +44,7 @@ namespace spot
/// ///
/// The resulting bitvect_array should be released with <code>delete</code>. /// The resulting bitvect_array should be released with <code>delete</code>.
SPOT_API bitvect_array* make_bitvect_array(size_t bitcount, SPOT_API bitvect_array* make_bitvect_array(size_t bitcount,
size_t vectcount); size_t vectcount);
/// \brief A bit vector /// \brief A bit vector
class SPOT_API bitvect class SPOT_API bitvect
@ -85,14 +85,14 @@ namespace spot
reserve_blocks(other.block_count_); reserve_blocks(other.block_count_);
size_ = other.size(); size_ = other.size();
for (size_t i = 0; i < block_count_; ++i) for (size_t i = 0; i < block_count_; ++i)
storage_[i] = other.storage_[i]; storage_[i] = other.storage_[i];
return *this; return *this;
} }
~bitvect() ~bitvect()
{ {
if (storage_ != &local_storage_) if (storage_ != &local_storage_)
free(storage_); free(storage_);
} }
/// Grow the bitvector to \a new_block_count blocks. /// Grow the bitvector to \a new_block_count blocks.
@ -101,20 +101,20 @@ namespace spot
void reserve_blocks(size_t new_block_count) void reserve_blocks(size_t new_block_count)
{ {
if (new_block_count < block_count_) if (new_block_count < block_count_)
return; return;
if (storage_ == &local_storage_) if (storage_ == &local_storage_)
{ {
block_t* new_storage_ = static_cast<block_t*> block_t* new_storage_ = static_cast<block_t*>
(malloc(new_block_count * sizeof(block_t))); (malloc(new_block_count * sizeof(block_t)));
for (size_t i = 0; i < block_count_; ++i) for (size_t i = 0; i < block_count_; ++i)
new_storage_[i] = storage_[i]; new_storage_[i] = storage_[i];
storage_ = new_storage_; storage_ = new_storage_;
} }
else else
{ {
storage_ = static_cast<block_t*> storage_ = static_cast<block_t*>
(realloc(storage_, new_block_count * sizeof(block_t))); (realloc(storage_, new_block_count * sizeof(block_t)));
} }
block_count_ = new_block_count; block_count_ = new_block_count;
} }
@ -137,44 +137,44 @@ namespace spot
void push_back(bool val) void push_back(bool val)
{ {
if (size() == capacity()) if (size() == capacity())
grow(); grow();
size_t pos = size_++; size_t pos = size_++;
if (val) if (val)
set(pos); set(pos);
else else
clear(pos); clear(pos);
} }
/// \brief Append the lowest \a count bits of \a data. /// \brief Append the lowest \a count bits of \a data.
void push_back(block_t data, unsigned count) void push_back(block_t data, unsigned count)
{ {
if (size() + count > capacity()) if (size() + count > capacity())
grow(); grow();
const size_t bpb = 8 * sizeof(block_t); const size_t bpb = 8 * sizeof(block_t);
// Clear the higher bits. // Clear the higher bits.
if (count != bpb) if (count != bpb)
data &= (1UL << count) - 1; data &= (1UL << count) - 1;
size_t n = size() % bpb; size_t n = size() % bpb;
size_t i = size_ / bpb; size_t i = size_ / bpb;
size_ += count; size_ += count;
if (n == 0) // Aligned on block_t boundary if (n == 0) // Aligned on block_t boundary
{ {
storage_[i] = data; storage_[i] = data;
} }
else // Only (bpb-n) bits free in this block. else // Only (bpb-n) bits free in this block.
{ {
// Take the lower bpb-n bits of data... // Take the lower bpb-n bits of data...
block_t mask = (1UL << (bpb - n)) - 1; block_t mask = (1UL << (bpb - n)) - 1;
block_t data1 = (data & mask) << n; block_t data1 = (data & mask) << n;
mask <<= n; mask <<= n;
// ... write them on the higher bpb-n bits of last block. // ... write them on the higher bpb-n bits of last block.
storage_[i] = (storage_[i] & ~mask) | data1; storage_[i] = (storage_[i] & ~mask) | data1;
// Write the remaining bits in the next block. // Write the remaining bits in the next block.
if (bpb - n < count) if (bpb - n < count)
storage_[i + 1] = data >> (bpb - n); storage_[i + 1] = data >> (bpb - n);
} }
} }
size_t size() const size_t size() const
@ -199,7 +199,7 @@ namespace spot
void clear_all() void clear_all()
{ {
for (size_t i = 0; i < block_count_; ++i) for (size_t i = 0; i < block_count_; ++i)
storage_[i] = 0; storage_[i] = 0;
} }
bool is_fully_clear() const bool is_fully_clear() const
@ -208,12 +208,12 @@ namespace spot
const size_t bpb = 8 * sizeof(bitvect::block_t); const size_t bpb = 8 * sizeof(bitvect::block_t);
size_t rest = size() % bpb; size_t rest = size() % bpb;
for (i = 0; i < block_count_ - !!rest; ++i) for (i = 0; i < block_count_ - !!rest; ++i)
if (storage_[i] != 0) if (storage_[i] != 0)
return false; return false;
// The last block might not be fully used, compare only the // The last block might not be fully used, compare only the
// relevant portion. // relevant portion.
if (!rest) if (!rest)
return true; return true;
block_t mask = (1UL << rest) - 1; block_t mask = (1UL << rest) - 1;
return (storage_[i] & mask) == 0; return (storage_[i] & mask) == 0;
} }
@ -224,10 +224,10 @@ namespace spot
const size_t bpb = 8 * sizeof(bitvect::block_t); const size_t bpb = 8 * sizeof(bitvect::block_t);
size_t rest = size() % bpb; size_t rest = size() % bpb;
for (i = 0; i < block_count_ - !!rest; ++i) for (i = 0; i < block_count_ - !!rest; ++i)
if (storage_[i] != -1UL) if (storage_[i] != -1UL)
return false; return false;
if (!rest) if (!rest)
return true; return true;
// The last block might not be fully used, compare only the // The last block might not be fully used, compare only the
// relevant portion. // relevant portion.
block_t mask = (1UL << rest) - 1; block_t mask = (1UL << rest) - 1;
@ -237,13 +237,13 @@ namespace spot
void set_all() void set_all()
{ {
for (size_t i = 0; i < block_count_; ++i) for (size_t i = 0; i < block_count_; ++i)
storage_[i] = -1UL; storage_[i] = -1UL;
} }
void flip_all() void flip_all()
{ {
for (size_t i = 0; i < block_count_; ++i) for (size_t i = 0; i < block_count_; ++i)
storage_[i] = ~storage_[i]; storage_[i] = ~storage_[i];
} }
void set(size_t pos) void set(size_t pos)
@ -273,7 +273,7 @@ namespace spot
assert(other.size_ <= size_); assert(other.size_ <= size_);
unsigned m = std::min(other.block_count_, block_count_); unsigned m = std::min(other.block_count_, block_count_);
for (size_t i = 0; i < m; ++i) for (size_t i = 0; i < m; ++i)
storage_[i] |= other.storage_[i]; storage_[i] |= other.storage_[i];
return *this; return *this;
} }
@ -282,7 +282,7 @@ namespace spot
assert(other.size_ <= size_); assert(other.size_ <= size_);
unsigned m = std::min(other.block_count_, block_count_); unsigned m = std::min(other.block_count_, block_count_);
for (size_t i = 0; i < m; ++i) for (size_t i = 0; i < m; ++i)
storage_[i] &= other.storage_[i]; storage_[i] &= other.storage_[i];
return *this; return *this;
} }
@ -291,7 +291,7 @@ namespace spot
assert(other.size_ <= size_); assert(other.size_ <= size_);
unsigned m = std::min(other.block_count_, block_count_); unsigned m = std::min(other.block_count_, block_count_);
for (size_t i = 0; i < m; ++i) for (size_t i = 0; i < m; ++i)
storage_[i] ^= other.storage_[i]; storage_[i] ^= other.storage_[i];
return *this; return *this;
} }
@ -299,7 +299,7 @@ namespace spot
{ {
assert(other.block_count_ <= block_count_); assert(other.block_count_ <= block_count_);
for (size_t i = 0; i < other.block_count_; ++i) for (size_t i = 0; i < other.block_count_; ++i)
storage_[i] &= ~other.storage_[i]; storage_[i] &= ~other.storage_[i];
return *this; return *this;
} }
@ -311,33 +311,33 @@ namespace spot
const size_t bpb = 8 * sizeof(bitvect::block_t); const size_t bpb = 8 * sizeof(bitvect::block_t);
size_t rest = size() % bpb; size_t rest = size() % bpb;
for (i = 0; i < block_count_ - !!rest; ++i) for (i = 0; i < block_count_ - !!rest; ++i)
if ((storage_[i] & other.storage_[i]) != other.storage_[i]) if ((storage_[i] & other.storage_[i]) != other.storage_[i])
return false; return false;
if (!rest) if (!rest)
return true; return true;
// The last block might not be fully used, compare only the // The last block might not be fully used, compare only the
// relevant portion. // relevant portion.
block_t mask = (1UL << rest) - 1; block_t mask = (1UL << rest) - 1;
return ((storage_[i] & mask & other.storage_[i]) return ((storage_[i] & mask & other.storage_[i])
== (other.storage_[i] & mask)); == (other.storage_[i] & mask));
} }
bool operator==(const bitvect& other) const bool operator==(const bitvect& other) const
{ {
if (other.size_ != size_) if (other.size_ != size_)
return false; return false;
if (size_ == 0) if (size_ == 0)
return true; return true;
size_t i; size_t i;
size_t m = other.used_blocks(); size_t m = other.used_blocks();
const size_t bpb = 8 * sizeof(bitvect::block_t); const size_t bpb = 8 * sizeof(bitvect::block_t);
size_t rest = size() % bpb; size_t rest = size() % bpb;
for (i = 0; i < m - !!rest; ++i) for (i = 0; i < m - !!rest; ++i)
if (storage_[i] != other.storage_[i]) if (storage_[i] != other.storage_[i])
return false; return false;
if (!rest) if (!rest)
return true; return true;
// The last block might not be fully used, compare only the // The last block might not be fully used, compare only the
// relevant portion. // relevant portion.
block_t mask = (1UL << rest) - 1; block_t mask = (1UL << rest) - 1;
@ -352,18 +352,18 @@ namespace spot
bool operator<(const bitvect& other) const bool operator<(const bitvect& other) const
{ {
if (size_ != other.size_) if (size_ != other.size_)
return size_ < other.size_; return size_ < other.size_;
if (size_ == 0) if (size_ == 0)
return false; return false;
size_t i; size_t i;
size_t m = other.used_blocks(); size_t m = other.used_blocks();
const size_t bpb = 8 * sizeof(bitvect::block_t); const size_t bpb = 8 * sizeof(bitvect::block_t);
size_t rest = size() % bpb; size_t rest = size() % bpb;
for (i = 0; i < m - !!rest; ++i) for (i = 0; i < m - !!rest; ++i)
if (storage_[i] > other.storage_[i]) if (storage_[i] > other.storage_[i])
return false; return false;
if (!rest) if (!rest)
return true; return true;
// The last block might not be fully used, compare only the // The last block might not be fully used, compare only the
// relevant portion. // relevant portion.
block_t mask = (1UL << rest) - 1; block_t mask = (1UL << rest) - 1;
@ -398,7 +398,7 @@ namespace spot
res->make_empty(); res->make_empty();
if (end == begin) if (end == begin)
return res; return res;
const size_t bpb = 8 * sizeof(bitvect::block_t); const size_t bpb = 8 * sizeof(bitvect::block_t);
@ -407,32 +407,32 @@ namespace spot
size_t indexe = (end - 1) / bpb; size_t indexe = (end - 1) / bpb;
if (indexb == indexe) if (indexb == indexe)
{ {
block_t data = storage_[indexb]; block_t data = storage_[indexb];
data >>= bitb; data >>= bitb;
res->push_back(data, count); res->push_back(data, count);
} }
else else
{ {
block_t data = storage_[indexb]; block_t data = storage_[indexb];
data >>= bitb; data >>= bitb;
res->push_back(data, bpb - bitb); res->push_back(data, bpb - bitb);
count -= bpb - bitb; count -= bpb - bitb;
while (count >= bpb) while (count >= bpb)
{ {
++indexb; ++indexb;
res->push_back(storage_[indexb], bpb); res->push_back(storage_[indexb], bpb);
count -= bpb; count -= bpb;
assert(indexb != indexe || count == 0); assert(indexb != indexe || count == 0);
} }
if (count > 0) if (count > 0)
{ {
++indexb; ++indexb;
assert(indexb == indexe); assert(indexb == indexe);
assert(count == end % bpb); assert(count == end % bpb);
res->push_back(storage_[indexb], count); res->push_back(storage_[indexb], count);
} }
} }
return res; return res;
} }
@ -441,12 +441,12 @@ namespace spot
/// Print a bitvect. /// Print a bitvect.
friend SPOT_API std::ostream& operator<<(std::ostream&, friend SPOT_API std::ostream& operator<<(std::ostream&,
const bitvect&); const bitvect&);
private: private:
friend SPOT_API bitvect_array* friend SPOT_API bitvect_array*
::spot::make_bitvect_array(size_t bitcount, ::spot::make_bitvect_array(size_t bitcount,
size_t vectcount); size_t vectcount);
size_t size_; size_t size_;
size_t block_count_; size_t block_count_;
@ -485,7 +485,7 @@ namespace spot
~bitvect_array() ~bitvect_array()
{ {
for (size_t i = 0; i < size_; ++i) for (size_t i = 0; i < size_; ++i)
at(i).~bitvect(); at(i).~bitvect();
} }
/// The number of bitvect in the array. /// The number of bitvect in the array.
@ -506,7 +506,7 @@ namespace spot
// FIXME: This could be changed into a large memset if the // FIXME: This could be changed into a large memset if the
// individual vectors where not allowed to be reallocated. // individual vectors where not allowed to be reallocated.
for (unsigned s = 0; s < size_; s++) for (unsigned s = 0; s < size_; s++)
at(s).clear_all(); at(s).clear_all();
} }
/// Return the bit-vector at \a index. /// Return the bit-vector at \a index.
@ -518,12 +518,12 @@ namespace spot
friend SPOT_API bitvect_array* friend SPOT_API bitvect_array*
::spot::make_bitvect_array(size_t bitcount, ::spot::make_bitvect_array(size_t bitcount,
size_t vectcount); size_t vectcount);
/// Print a bitvect_array. /// Print a bitvect_array.
friend SPOT_API std::ostream& operator<<(std::ostream&, friend SPOT_API std::ostream& operator<<(std::ostream&,
const bitvect_array&); const bitvect_array&);
private: private:
size_t size_; size_t size_;

View file

@ -93,9 +93,9 @@
// The extra parentheses in assert() is so that this // The extra parentheses in assert() is so that this
// pattern is not caught by the style checker. // pattern is not caught by the style checker.
#define SPOT_UNREACHABLE() do { \ #define SPOT_UNREACHABLE() do { \
assert(!("unreachable code reached")); \ assert(!("unreachable code reached")); \
SPOT_UNREACHABLE_BUILTIN(); \ SPOT_UNREACHABLE_BUILTIN(); \
} while (0) } while (0)
#define SPOT_UNIMPLEMENTED() throw std::runtime_error("unimplemented"); #define SPOT_UNIMPLEMENTED() throw std::runtime_error("unimplemented");

View file

@ -33,14 +33,14 @@ namespace spot
{ {
for (auto i: str) for (auto i: str)
switch (i) switch (i)
{ {
case '"': case '"':
os << "\"\""; os << "\"\"";
break; break;
default: default:
os << i; os << i;
break; break;
} }
return os; return os;
} }
@ -49,28 +49,28 @@ namespace spot
{ {
for (auto i: str) for (auto i: str)
switch (i) switch (i)
{ {
case '~': case '~':
os << "\\text{\\textasciitilde}"; os << "\\text{\\textasciitilde}";
break; break;
case '^': case '^':
os << "\\text{\\textasciicircum}"; os << "\\text{\\textasciicircum}";
break; break;
case '\\': case '\\':
os << "\\text{\\textbackslash}"; os << "\\text{\\textbackslash}";
break; break;
case '&': case '&':
case '%': case '%':
case '$': case '$':
case '#': case '#':
case '_': case '_':
case '{': case '{':
case '}': case '}':
os << '\\'; os << '\\';
default: default:
os << i; os << i;
break; break;
} }
return os; return os;
} }
@ -79,23 +79,23 @@ namespace spot
{ {
for (auto i: str) for (auto i: str)
switch (i) switch (i)
{ {
case '&': case '&':
os << "&amp;"; os << "&amp;";
break; break;
case '"': case '"':
os << "&quot;"; os << "&quot;";
break; break;
case '<': case '<':
os << "&lt;"; os << "&lt;";
break; break;
case '>': case '>':
os << "&gt;"; os << "&gt;";
break; break;
default: default:
os << i; os << i;
break; break;
} }
return os; return os;
} }
@ -104,20 +104,20 @@ namespace spot
{ {
for (auto i: str) for (auto i: str)
switch (i) switch (i)
{ {
case '\\': case '\\':
os << "\\\\"; os << "\\\\";
break; break;
case '"': case '"':
os << "\\\""; os << "\\\"";
break; break;
case '\n': case '\n':
os << "\\n"; os << "\\n";
break; break;
default: default:
os << i; os << i;
break; break;
} }
return os; return os;
} }
@ -135,26 +135,26 @@ namespace spot
// Single quotes are best, unless the string to quote contains one. // Single quotes are best, unless the string to quote contains one.
if (!strchr(str, '\'')) if (!strchr(str, '\''))
{ {
os << '\'' << str << '\''; os << '\'' << str << '\'';
} }
else else
{ {
// In double quotes we have to escape $ ` " or \. // In double quotes we have to escape $ ` " or \.
os << '"'; os << '"';
while (*str) while (*str)
switch (*str) switch (*str)
{ {
case '$': case '$':
case '`': case '`':
case '"': case '"':
case '\\': case '\\':
os << '\\'; os << '\\';
// fall through // fall through
default: default:
os << *str++; os << *str++;
break; break;
} }
os << '"'; os << '"';
} }
return os; return os;
} }

View file

@ -34,22 +34,22 @@ namespace spot
/// Create a pool allocating objects of \a size bytes. /// Create a pool allocating objects of \a size bytes.
fixed_size_pool(size_t size) fixed_size_pool(size_t size)
: freelist_(nullptr), free_start_(nullptr), : freelist_(nullptr), free_start_(nullptr),
free_end_(nullptr), chunklist_(nullptr) free_end_(nullptr), chunklist_(nullptr)
{ {
const size_t alignement = 2 * sizeof(size_t); const size_t alignement = 2 * sizeof(size_t);
size_ = ((size >= sizeof(block_) ? size : sizeof(block_)) size_ = ((size >= sizeof(block_) ? size : sizeof(block_))
+ alignement - 1) & ~(alignement - 1); + alignement - 1) & ~(alignement - 1);
} }
/// Free any memory allocated by this pool. /// Free any memory allocated by this pool.
~fixed_size_pool() ~fixed_size_pool()
{ {
while (chunklist_) while (chunklist_)
{ {
chunk_* prev = chunklist_->prev; chunk_* prev = chunklist_->prev;
free(chunklist_); free(chunklist_);
chunklist_ = prev; chunklist_ = prev;
} }
} }
/// Allocate \a size bytes of memory. /// Allocate \a size bytes of memory.
@ -59,27 +59,27 @@ namespace spot
block_* f = freelist_; block_* f = freelist_;
// If we have free blocks available, return the first one. // If we have free blocks available, return the first one.
if (f) if (f)
{ {
freelist_ = f->next; freelist_ = f->next;
return f; return f;
} }
// Else, create a block out of the last chunk of allocated // Else, create a block out of the last chunk of allocated
// memory. // memory.
// If all the last chunk has been used, allocate one more. // If all the last chunk has been used, allocate one more.
if (free_start_ + size_ > free_end_) if (free_start_ + size_ > free_end_)
{ {
const size_t requested = (size_ > 128 ? size_ : 128) * 8192 - 64; const size_t requested = (size_ > 128 ? size_ : 128) * 8192 - 64;
chunk_* c = reinterpret_cast<chunk_*>(malloc(requested)); chunk_* c = reinterpret_cast<chunk_*>(malloc(requested));
if (!c) if (!c)
throw std::bad_alloc(); throw std::bad_alloc();
c->prev = chunklist_; c->prev = chunklist_;
chunklist_ = c; chunklist_ = c;
free_start_ = c->data_ + size_; free_start_ = c->data_ + size_;
free_end_ = c->data_ + requested; free_end_ = c->data_ + requested;
} }
void* res = free_start_; void* res = free_start_;
free_start_ += size_; free_start_ += size_;

View file

@ -28,12 +28,12 @@ namespace spot
{ {
for (const char* pos = fmt; *pos; ++pos) for (const char* pos = fmt; *pos; ++pos)
if (*pos == '%') if (*pos == '%')
{ {
char c = *++pos; char c = *++pos;
has[c] = true; has[c] = true;
if (!c) if (!c)
break; break;
} }
} }
void void
@ -46,17 +46,17 @@ namespace spot
formater::format(const char* fmt) formater::format(const char* fmt)
{ {
for (const char* pos = fmt; *pos; ++pos) for (const char* pos = fmt; *pos; ++pos)
if (*pos != '%') if (*pos != '%')
{ {
*output_ << *pos; *output_ << *pos;
} }
else else
{ {
char c = *++pos; char c = *++pos;
call_[c]->print(*output_, pos); call_[c]->print(*output_, pos);
if (!c) if (!c)
break; break;
} }
return *output_; return *output_;
} }
} }

View file

@ -49,7 +49,7 @@ namespace spot
size_t operator()(const T* p) const size_t operator()(const T* p) const
{ {
return knuth32_hash(reinterpret_cast<const char*>(p) return knuth32_hash(reinterpret_cast<const char*>(p)
- static_cast<const char*>(nullptr)); - static_cast<const char*>(nullptr));
} }
}; };
@ -85,7 +85,7 @@ namespace spot
std::hash<U> uh; std::hash<U> uh;
return wang32_hash(static_cast<size_t>(th(p.first)) ^ return wang32_hash(static_cast<size_t>(th(p.first)) ^
static_cast<size_t>(uh(p.second))); static_cast<size_t>(uh(p.second)));
} }
}; };
} }

View file

@ -43,270 +43,270 @@ namespace spot
{ {
public: public:
stream_compression_base(size_t size) stream_compression_base(size_t size)
: size_(size) : size_(size)
{ {
} }
void run() void run()
{ {
static const unsigned bits_width[7] = { 1, 3, 5, 7, 9, 14, 28 }; 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_count[8] = { 30, 10, 6, 4, 3, 2, 1, 0 };
static const unsigned max_allowed[8] = { 1, static const unsigned max_allowed[8] = { 1,
(1 << 3) - 1, (1 << 3) - 1,
(1 << 5) - 1, (1 << 5) - 1,
(1 << 7) - 1, (1 << 7) - 1,
(1 << 9) - 1, (1 << 9) - 1,
(1 << 14) - 1, (1 << 14) - 1,
(1 << 28) - 1, (1 << 28) - 1,
-1U }; -1U };
// If we have only X data to compress and they fit with the // If we have only X data to compress and they fit with the
// current bit width, the following table tells us we should // current bit width, the following table tells us we should
// use bits_width[count_to_level[X - 1]] to limit the number // use bits_width[count_to_level[X - 1]] to limit the number
// of trailing zeros we encode. E.g. count_to_level[5 - 1] // of trailing zeros we encode. E.g. count_to_level[5 - 1]
// is 2, which mean that 5 values should be encoded with // is 2, which mean that 5 values should be encoded with
// bits_width[2] == 5 bits. // bits_width[2] == 5 bits.
static const unsigned count_to_level[30] = static const unsigned count_to_level[30] =
{ {
6, // 1 6, // 1
5, // 2 5, // 2
4, // 3 4, // 3
3, // 4 3, // 4
2, // 5 2, // 5
2, // 6 2, // 6
1, // 7 1, // 7
1, // 8 1, // 8
1, // 9 1, // 9
1, // 10 1, // 10
0, 0, 0, 0, 0, // 11-15 0, 0, 0, 0, 0, // 11-15
0, 0, 0, 0, 0, // 16-20 0, 0, 0, 0, 0, // 16-20
0, 0, 0, 0, 0, // 21-25 0, 0, 0, 0, 0, // 21-25
0, 0, 0, 0, 0, // 26-30 0, 0, 0, 0, 0, // 26-30
}; };
while (size_ > 0) while (size_ > 0)
{ {
unsigned id = 0; // Current level in the above two tables. unsigned id = 0; // Current level in the above two tables.
unsigned curmax_allowed = max_allowed[id]; unsigned curmax_allowed = max_allowed[id];
unsigned compressable = 0; // Number of integers ready to pack. unsigned compressable = 0; // Number of integers ready to pack.
do do
{ {
unsigned int val = self().data_at(compressable); unsigned int val = self().data_at(compressable);
++compressable; ++compressable;
while (val > curmax_allowed) while (val > curmax_allowed)
{ {
curmax_allowed = max_allowed[++id]; curmax_allowed = max_allowed[++id];
if (compressable > max_count[id]) if (compressable > max_count[id])
goto fast_encode; goto fast_encode;
} }
if (compressable >= max_count[id]) if (compressable >= max_count[id])
goto fast_encode; goto fast_encode;
} }
while (SPOT_LIKELY(compressable < size_)); 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, // Since we have less data than the current "id" allows,
// try to use more bits so we can encode faster. // 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]) if (compressable == max_count[id])
goto fast_encode; goto fast_encode;
// Slow compression for situations where we have // Slow compression for situations where we have
// compressable < max_count[id]. We can only be in // compressable < max_count[id]. We can only be in
// one of the 3 first "id" (1, 3, or 5 bits); // one of the 3 first "id" (1, 3, or 5 bits);
{ {
assert(id <= 2); assert(id <= 2);
unsigned bits = bits_width[id]; unsigned bits = bits_width[id];
unsigned finalshifts = (max_count[id] - compressable) * bits; unsigned finalshifts = (max_count[id] - compressable) * bits;
size_t pos = 0; size_t pos = 0;
unsigned output = self().data_at(pos); unsigned output = self().data_at(pos);
while (--compressable) while (--compressable)
{ {
output <<= bits; output <<= bits;
output += self().data_at(++pos); output += self().data_at(++pos);
} }
output <<= finalshifts; output <<= finalshifts;
output += id << 30; output += id << 30;
self().push_data(output); self().push_data(output);
return; return;
} }
fast_encode: fast_encode:
switch (id) switch (id)
{ {
case 0: // 30 1-bit values case 0: // 30 1-bit values
{ {
// This code has been tuned so that the compiler can // This code has been tuned so that the compiler can
// efficiently encode it as a series of MOV+LEA // efficiently encode it as a series of MOV+LEA
// instructions, without shifts. For instance // instructions, without shifts. For instance
// //
// output <<= 1; // output <<= 1;
// output += self().data_at(4); // output += self().data_at(4);
// //
// translates to (assuming %eax points to the input, // translates to (assuming %eax points to the input,
// and %edx holds the output) the following: // and %edx holds the output) the following:
// //
// mov ecx, [eax+16] // mov ecx, [eax+16]
// lea edx, [ecx+edx*2] // lea edx, [ecx+edx*2]
// //
// This optimization is the reason why we use 'output +=' // This optimization is the reason why we use 'output +='
// instead of the more intuitive 'output |=' everywhere in // instead of the more intuitive 'output |=' everywhere in
// this file. // this file.
unsigned int output = 0x00 << 1; // 00 unsigned int output = 0x00 << 1; // 00
output += self().data_at(0); output += self().data_at(0);
output <<= 1; output <<= 1;
output += self().data_at(1); output += self().data_at(1);
output <<= 1; output <<= 1;
output += self().data_at(2); output += self().data_at(2);
output <<= 1; output <<= 1;
output += self().data_at(3); output += self().data_at(3);
output <<= 1; output <<= 1;
output += self().data_at(4); output += self().data_at(4);
output <<= 1; output <<= 1;
output += self().data_at(5); output += self().data_at(5);
output <<= 1; output <<= 1;
output += self().data_at(6); output += self().data_at(6);
output <<= 1; output <<= 1;
output += self().data_at(7); output += self().data_at(7);
output <<= 1; output <<= 1;
output += self().data_at(8); output += self().data_at(8);
output <<= 1; output <<= 1;
output += self().data_at(9); output += self().data_at(9);
output <<= 1; output <<= 1;
output += self().data_at(10); output += self().data_at(10);
output <<= 1; output <<= 1;
output += self().data_at(11); output += self().data_at(11);
output <<= 1; output <<= 1;
output += self().data_at(12); output += self().data_at(12);
output <<= 1; output <<= 1;
output += self().data_at(13); output += self().data_at(13);
output <<= 1; output <<= 1;
output += self().data_at(14); output += self().data_at(14);
output <<= 1; output <<= 1;
output += self().data_at(15); output += self().data_at(15);
output <<= 1; output <<= 1;
output += self().data_at(16); output += self().data_at(16);
output <<= 1; output <<= 1;
output += self().data_at(17); output += self().data_at(17);
output <<= 1; output <<= 1;
output += self().data_at(18); output += self().data_at(18);
output <<= 1; output <<= 1;
output += self().data_at(19); output += self().data_at(19);
output <<= 1; output <<= 1;
output += self().data_at(20); output += self().data_at(20);
output <<= 1; output <<= 1;
output += self().data_at(21); output += self().data_at(21);
output <<= 1; output <<= 1;
output += self().data_at(22); output += self().data_at(22);
output <<= 1; output <<= 1;
output += self().data_at(23); output += self().data_at(23);
output <<= 1; output <<= 1;
output += self().data_at(24); output += self().data_at(24);
output <<= 1; output <<= 1;
output += self().data_at(25); output += self().data_at(25);
output <<= 1; output <<= 1;
output += self().data_at(26); output += self().data_at(26);
output <<= 1; output <<= 1;
output += self().data_at(27); output += self().data_at(27);
output <<= 1; output <<= 1;
output += self().data_at(28); output += self().data_at(28);
output <<= 1; output <<= 1;
output += self().data_at(29); output += self().data_at(29);
self().push_data(output); self().push_data(output);
} }
break; break;
case 1: // 10 3-bit values case 1: // 10 3-bit values
{ {
// This code has been tuned so that the compiler can // This code has been tuned so that the compiler can
// efficiently encode it as a series of MOV+LEA // efficiently encode it as a series of MOV+LEA
// instructions, without shifts. For instance // instructions, without shifts. For instance
// //
// output <<= 3; // output <<= 3;
// output += self().data_at(4); // output += self().data_at(4);
// //
// translates to (assuming %eax points to the input, // translates to (assuming %eax points to the input,
// and %edx holds the output) the following: // and %edx holds the output) the following:
// //
// mov ecx, [eax+16] // mov ecx, [eax+16]
// lea edx, [ecx+edx*8] // lea edx, [ecx+edx*8]
unsigned int output = 0x01 << 3; // 01 unsigned int output = 0x01 << 3; // 01
output += self().data_at(0); output += self().data_at(0);
output <<= 3; output <<= 3;
output += self().data_at(1); output += self().data_at(1);
output <<= 3; output <<= 3;
output += self().data_at(2); output += self().data_at(2);
output <<= 3; output <<= 3;
output += self().data_at(3); output += self().data_at(3);
output <<= 3; output <<= 3;
output += self().data_at(4); output += self().data_at(4);
output <<= 3; output <<= 3;
output += self().data_at(5); output += self().data_at(5);
output <<= 3; output <<= 3;
output += self().data_at(6); output += self().data_at(6);
output <<= 3; output <<= 3;
output += self().data_at(7); output += self().data_at(7);
output <<= 3; output <<= 3;
output += self().data_at(8); output += self().data_at(8);
output <<= 3; output <<= 3;
output += self().data_at(9); output += self().data_at(9);
self().push_data(output); self().push_data(output);
} }
break; break;
case 2: // 6 5-bit values case 2: // 6 5-bit values
{ {
unsigned int output = 0x02U << 30; // 10 unsigned int output = 0x02U << 30; // 10
output += self().data_at(0) << 25; output += self().data_at(0) << 25;
output += self().data_at(1) << 20; output += self().data_at(1) << 20;
output += self().data_at(2) << 15; output += self().data_at(2) << 15;
output += self().data_at(3) << 10; output += self().data_at(3) << 10;
output += self().data_at(4) << 5; output += self().data_at(4) << 5;
output += self().data_at(5); output += self().data_at(5);
self().push_data(output); self().push_data(output);
} }
break; break;
case 3: // 4 7-bit values case 3: // 4 7-bit values
{ {
unsigned int output = 0x0CU << 28; // 1100 unsigned int output = 0x0CU << 28; // 1100
output += self().data_at(0) << 21; output += self().data_at(0) << 21;
output += self().data_at(1) << 14; output += self().data_at(1) << 14;
output += self().data_at(2) << 7; output += self().data_at(2) << 7;
output += self().data_at(3); output += self().data_at(3);
self().push_data(output); self().push_data(output);
} }
break; break;
case 4: // 3 9-bit values case 4: // 3 9-bit values
{ {
unsigned int output = 0x0DU << 28; // 1101x (1 bit lost) unsigned int output = 0x0DU << 28; // 1101x (1 bit lost)
output += self().data_at(0) << 18; output += self().data_at(0) << 18;
output += self().data_at(1) << 9; output += self().data_at(1) << 9;
output += self().data_at(2); output += self().data_at(2);
self().push_data(output); self().push_data(output);
} }
break; break;
case 5: // 2 14-bit values case 5: // 2 14-bit values
{ {
unsigned int output = 0x0EU << 28; // 1110 unsigned int output = 0x0EU << 28; // 1110
output += self().data_at(0) << 14; output += self().data_at(0) << 14;
output += self().data_at(1); output += self().data_at(1);
self().push_data(output); self().push_data(output);
} }
break; break;
case 6: // one 28-bit value case 6: // one 28-bit value
{ {
unsigned int output = 0x0FU << 28; // 1111 unsigned int output = 0x0FU << 28; // 1111
output += self().data_at(0); output += self().data_at(0);
self().push_data(output); self().push_data(output);
} }
break; break;
} }
self().forward(max_count[id]); self().forward(max_count[id]);
size_ -= max_count[id]; size_ -= max_count[id];
} }
} }
protected: protected:
@ -315,12 +315,12 @@ namespace spot
Self& self() Self& self()
{ {
return static_cast<Self&>(*this); return static_cast<Self&>(*this);
} }
const Self& self() const const Self& self() const
{ {
return static_cast<const Self&>(*this); return static_cast<const Self&>(*this);
} }
}; };
@ -331,29 +331,29 @@ namespace spot
{ {
public: public:
int_array_array_compression(const int* array, size_t n, int_array_array_compression(const int* array, size_t n,
int* dest, size_t& dest_n) int* dest, size_t& dest_n)
: stream_compression_base<int_array_array_compression>(n), : stream_compression_base<int_array_array_compression>(n),
array_(array), result_size_(dest_n), array_(array), result_size_(dest_n),
result_(dest), result_end_(dest + 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) void push_data(unsigned int i)
{ {
assert(result_ < result_end_); assert(result_ < result_end_);
++result_size_; ++result_size_;
*result_++ = static_cast<int>(i); *result_++ = static_cast<int>(i);
} }
unsigned int data_at(size_t offset) unsigned int data_at(size_t offset)
{ {
return static_cast<unsigned int>(array_[offset]); return static_cast<unsigned int>(array_[offset]);
} }
void forward(size_t offset) void forward(size_t offset)
{ {
array_ += offset; array_ += offset;
} }
protected: protected:
@ -368,7 +368,7 @@ namespace spot
void void
int_array_array_compress2(const int* array, size_t n, 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); int_array_array_compression c(array, n, dest, dest_size);
c.run(); c.run();
@ -386,113 +386,113 @@ namespace spot
void run() void run()
{ {
while (SPOT_LIKELY(self().have_comp_data())) while (SPOT_LIKELY(self().have_comp_data()))
{ {
unsigned val = self().next_comp_data(); unsigned val = self().next_comp_data();
unsigned id = val >> 28; unsigned id = val >> 28;
switch (id) switch (id)
{ {
case 0x00: // 00xx - 30 1-bit values. case 0x00: // 00xx - 30 1-bit values.
case 0x01: case 0x01:
case 0x02: case 0x02:
case 0x03: case 0x03:
self().write_data_at(0, !!(val & (1 << 29))); self().write_data_at(0, !!(val & (1 << 29)));
self().write_data_at(1, !!(val & (1 << 28))); self().write_data_at(1, !!(val & (1 << 28)));
self().write_data_at(2, !!(val & (1 << 27))); self().write_data_at(2, !!(val & (1 << 27)));
self().write_data_at(3, !!(val & (1 << 26))); self().write_data_at(3, !!(val & (1 << 26)));
self().write_data_at(4, !!(val & (1 << 25))); self().write_data_at(4, !!(val & (1 << 25)));
self().write_data_at(5, !!(val & (1 << 24))); self().write_data_at(5, !!(val & (1 << 24)));
self().write_data_at(6, !!(val & (1 << 23))); self().write_data_at(6, !!(val & (1 << 23)));
self().write_data_at(7, !!(val & (1 << 22))); self().write_data_at(7, !!(val & (1 << 22)));
self().write_data_at(8, !!(val & (1 << 21))); self().write_data_at(8, !!(val & (1 << 21)));
self().write_data_at(9, !!(val & (1 << 20))); self().write_data_at(9, !!(val & (1 << 20)));
self().write_data_at(10, !!(val & (1 << 19))); self().write_data_at(10, !!(val & (1 << 19)));
self().write_data_at(11, !!(val & (1 << 18))); self().write_data_at(11, !!(val & (1 << 18)));
self().write_data_at(12, !!(val & (1 << 17))); self().write_data_at(12, !!(val & (1 << 17)));
self().write_data_at(13, !!(val & (1 << 16))); self().write_data_at(13, !!(val & (1 << 16)));
self().write_data_at(14, !!(val & (1 << 15))); self().write_data_at(14, !!(val & (1 << 15)));
self().write_data_at(15, !!(val & (1 << 14))); self().write_data_at(15, !!(val & (1 << 14)));
self().write_data_at(16, !!(val & (1 << 13))); self().write_data_at(16, !!(val & (1 << 13)));
self().write_data_at(17, !!(val & (1 << 12))); self().write_data_at(17, !!(val & (1 << 12)));
self().write_data_at(18, !!(val & (1 << 11))); self().write_data_at(18, !!(val & (1 << 11)));
self().write_data_at(19, !!(val & (1 << 10))); self().write_data_at(19, !!(val & (1 << 10)));
self().write_data_at(20, !!(val & (1 << 9))); self().write_data_at(20, !!(val & (1 << 9)));
self().write_data_at(21, !!(val & (1 << 8))); self().write_data_at(21, !!(val & (1 << 8)));
self().write_data_at(22, !!(val & (1 << 7))); self().write_data_at(22, !!(val & (1 << 7)));
self().write_data_at(23, !!(val & (1 << 6))); self().write_data_at(23, !!(val & (1 << 6)));
self().write_data_at(24, !!(val & (1 << 5))); self().write_data_at(24, !!(val & (1 << 5)));
self().write_data_at(25, !!(val & (1 << 4))); self().write_data_at(25, !!(val & (1 << 4)));
self().write_data_at(26, !!(val & (1 << 3))); self().write_data_at(26, !!(val & (1 << 3)));
self().write_data_at(27, !!(val & (1 << 2))); self().write_data_at(27, !!(val & (1 << 2)));
self().write_data_at(28, !!(val & (1 << 1))); self().write_data_at(28, !!(val & (1 << 1)));
self().write_data_at(29, !!(val & (1 << 0))); self().write_data_at(29, !!(val & (1 << 0)));
self().forward(30); self().forward(30);
break; break;
case 0x04: // 01xx - 10 3-bit values. case 0x04: // 01xx - 10 3-bit values.
case 0x05: case 0x05:
case 0x06: case 0x06:
case 0x07: case 0x07:
self().write_data_at(0, (val >> 27) & 0x07); self().write_data_at(0, (val >> 27) & 0x07);
self().write_data_at(1, (val >> 24) & 0x07); self().write_data_at(1, (val >> 24) & 0x07);
self().write_data_at(2, (val >> 21) & 0x07); self().write_data_at(2, (val >> 21) & 0x07);
self().write_data_at(3, (val >> 18) & 0x07); self().write_data_at(3, (val >> 18) & 0x07);
self().write_data_at(4, (val >> 15) & 0x07); self().write_data_at(4, (val >> 15) & 0x07);
self().write_data_at(5, (val >> 12) & 0x07); self().write_data_at(5, (val >> 12) & 0x07);
self().write_data_at(6, (val >> 9) & 0x07); self().write_data_at(6, (val >> 9) & 0x07);
self().write_data_at(7, (val >> 6) & 0x07); self().write_data_at(7, (val >> 6) & 0x07);
self().write_data_at(8, (val >> 3) & 0x07); self().write_data_at(8, (val >> 3) & 0x07);
self().write_data_at(9, (val >> 0) & 0x07); self().write_data_at(9, (val >> 0) & 0x07);
self().forward(10); self().forward(10);
break; break;
case 0x08: // 10xx - 6 5-bit values. case 0x08: // 10xx - 6 5-bit values.
case 0x09: case 0x09:
case 0x0A: case 0x0A:
case 0x0B: case 0x0B:
self().write_data_at(0, (val >> 25) & 0x1F); self().write_data_at(0, (val >> 25) & 0x1F);
self().write_data_at(1, (val >> 20) & 0x1F); self().write_data_at(1, (val >> 20) & 0x1F);
self().write_data_at(2, (val >> 15) & 0x1F); self().write_data_at(2, (val >> 15) & 0x1F);
self().write_data_at(3, (val >> 10) & 0x1F); self().write_data_at(3, (val >> 10) & 0x1F);
self().write_data_at(4, (val >> 5) & 0x1F); self().write_data_at(4, (val >> 5) & 0x1F);
self().write_data_at(5, (val >> 0) & 0x1F); self().write_data_at(5, (val >> 0) & 0x1F);
self().forward(6); self().forward(6);
break; break;
case 0x0C: // 1100 - 4 7-bit values case 0x0C: // 1100 - 4 7-bit values
self().write_data_at(0, (val >> 21) & 0x7F); self().write_data_at(0, (val >> 21) & 0x7F);
self().write_data_at(1, (val >> 14) & 0x7F); self().write_data_at(1, (val >> 14) & 0x7F);
self().write_data_at(2, (val >> 7) & 0x7F); self().write_data_at(2, (val >> 7) & 0x7F);
self().write_data_at(3, (val >> 0) & 0x7F); self().write_data_at(3, (val >> 0) & 0x7F);
self().forward(4); self().forward(4);
break; break;
case 0x0D: // 1101x - 3 9-bit values. case 0x0D: // 1101x - 3 9-bit values.
self().write_data_at(0, (val >> 18) & 0x1FF); self().write_data_at(0, (val >> 18) & 0x1FF);
self().write_data_at(1, (val >> 9) & 0x1FF); self().write_data_at(1, (val >> 9) & 0x1FF);
self().write_data_at(2, (val >> 0) & 0x1FF); self().write_data_at(2, (val >> 0) & 0x1FF);
self().forward(3); self().forward(3);
break; break;
case 0x0E: // 110x - 2 14-bit values. case 0x0E: // 110x - 2 14-bit values.
self().write_data_at(0, (val >> 14) & 0x3FFF); self().write_data_at(0, (val >> 14) & 0x3FFF);
self().write_data_at(1, (val >> 0) & 0x3FFF); self().write_data_at(1, (val >> 0) & 0x3FFF);
self().forward(2); self().forward(2);
break; break;
case 0x0F: // 1100 - 1 28-bit value. case 0x0F: // 1100 - 1 28-bit value.
self().write_data_at(0, val & 0xFFFFFFF); self().write_data_at(0, val & 0xFFFFFFF);
self().forward(1); self().forward(1);
break; break;
} }
} }
} }
protected: protected:
Self& self() Self& self()
{ {
return static_cast<Self&>(*this); return static_cast<Self&>(*this);
} }
const Self& self() const const Self& self() const
{ {
return static_cast<const Self&>(*this); return static_cast<const Self&>(*this);
} }
}; };
@ -502,30 +502,30 @@ namespace spot
{ {
public: public:
int_array_array_decompression(const int* array, int_array_array_decompression(const int* array,
size_t array_size, size_t array_size,
int* res) int* res)
: array_(array), n_(array_size), pos_(0), result_(res) : array_(array), n_(array_size), pos_(0), result_(res)
{ {
} }
void write_data_at(size_t pos, unsigned int i) void write_data_at(size_t pos, unsigned int i)
{ {
result_[pos] = i; result_[pos] = i;
} }
void forward(size_t i) void forward(size_t i)
{ {
result_ += i; result_ += i;
} }
bool have_comp_data() const bool have_comp_data() const
{ {
return pos_ < n_; return pos_ < n_;
} }
unsigned int next_comp_data() unsigned int next_comp_data()
{ {
return array_[pos_++]; return array_[pos_++];
} }
protected: protected:
@ -540,7 +540,7 @@ namespace spot
void void
int_array_array_decompress2(const int* array, size_t array_size, int* res, 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); int_array_array_decompression c(array, array_size, res);
c.run(); c.run();

View file

@ -36,7 +36,7 @@ namespace spot
/// filled in \a dest /// filled in \a dest
SPOT_API void SPOT_API void
int_array_array_compress2(const int* array, size_t n, 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 /// \brief Uncompress an int array of size \a array_size into a int
/// array of size \a size. /// array of size \a size.
@ -44,7 +44,7 @@ namespace spot
/// \a size must be the exact expected size of uncompressed array. /// \a size must be the exact expected size of uncompressed array.
SPOT_API void SPOT_API void
int_array_array_decompress2(const int* array, size_t array_size, int_array_array_decompress2(const int* array, size_t array_size,
int* res, size_t size); int* res, size_t size);
/// @} /// @}
} }

View file

@ -55,129 +55,129 @@ namespace spot
public: public:
stream_compression_base() stream_compression_base()
: cur_(0), bits_left_(max_bits) : cur_(0), bits_left_(max_bits)
{ {
} }
void emit(unsigned int val) void emit(unsigned int val)
{ {
if (val == 0) if (val == 0)
{ {
self().push_bits(0x0, 2, 0x3); self().push_bits(0x0, 2, 0x3);
} }
else if (val == 1) else if (val == 1)
{ {
self().push_bits(0x2, 3, 0x7); self().push_bits(0x2, 3, 0x7);
} }
else if (val >= 2 && val <= 5) else if (val >= 2 && val <= 5)
{ {
self().push_bits(0x3, 3, 0x7); self().push_bits(0x3, 3, 0x7);
self().push_bits(val - 2, 2, 0x3); self().push_bits(val - 2, 2, 0x3);
} }
else if (val >= 6 && val <= 22) else if (val >= 6 && val <= 22)
{ {
self().push_bits(0x4, 3, 0x7); self().push_bits(0x4, 3, 0x7);
self().push_bits(val - 6, 4, 0xf); self().push_bits(val - 6, 4, 0xf);
} }
else else
{ {
assert(val > 22); assert(val > 22);
self().push_bits(0x7, 3, 0x7); self().push_bits(0x7, 3, 0x7);
self().push_bits(val, 32, -1U); self().push_bits(val, 32, -1U);
} }
} }
void run() void run()
{ {
unsigned int last_val = 0; unsigned int last_val = 0;
while (SPOT_LIKELY(self().have_data())) while (SPOT_LIKELY(self().have_data()))
{ {
unsigned int val = self().next_data(); unsigned int val = self().next_data();
// Repeated value? Try to find more. // Repeated value? Try to find more.
if (val == last_val) if (val == last_val)
{ {
unsigned int count = 1; unsigned int count = 1;
while (count < 40 && self().skip_if(val)) while (count < 40 && self().skip_if(val))
++count; ++count;
if ((val == 0 && count < 3) || (val == 1 && count == 1)) if ((val == 0 && count < 3) || (val == 1 && count == 1))
{ {
// it is more efficient to emit 0 once or twice directly // it is more efficient to emit 0 once or twice directly
// (e.g., 00 00 vs. 011 11) // (e.g., 00 00 vs. 011 11)
// for value 1, repetition is worthwhile for count > 1 // for value 1, repetition is worthwhile for count > 1
// (e.g., 010 010 vs. 011 00) // (e.g., 010 010 vs. 011 00)
while (count--) while (count--)
emit(val); emit(val);
} }
else if (count < 9) else if (count < 9)
{ {
self().push_bits(0x5, 3, 0x7); self().push_bits(0x5, 3, 0x7);
self().push_bits(count - 1, 3, 0x7); self().push_bits(count - 1, 3, 0x7);
} }
else else
{ {
self().push_bits(0x6, 3, 0x7); self().push_bits(0x6, 3, 0x7);
self().push_bits(count - 9, 5, 0x1f); self().push_bits(count - 9, 5, 0x1f);
} }
} }
else else
{ {
emit(val); emit(val);
last_val = val; last_val = val;
} }
} }
flush(); flush();
} }
// This version assumes there is at least n bits free in cur_. // This version assumes there is at least n bits free in cur_.
void void
push_bits_unchecked(unsigned int bits, unsigned int n, unsigned int mask) push_bits_unchecked(unsigned int bits, unsigned int n, unsigned int mask)
{ {
cur_ <<= n; cur_ <<= n;
cur_ |= (bits & mask); cur_ |= (bits & mask);
if (SPOT_LIKELY(bits_left_ -= n)) if (SPOT_LIKELY(bits_left_ -= n))
return; return;
self().push_data(cur_); self().push_data(cur_);
cur_ = 0; cur_ = 0;
bits_left_ = max_bits; bits_left_ = max_bits;
} }
void void
push_bits(unsigned int bits, unsigned int n, unsigned int mask) push_bits(unsigned int bits, unsigned int n, unsigned int mask)
{ {
if (SPOT_LIKELY(n <= bits_left_)) if (SPOT_LIKELY(n <= bits_left_))
{ {
push_bits_unchecked(bits, n, mask); push_bits_unchecked(bits, n, mask);
return; return;
} }
// bits_left_ < n // bits_left_ < n
unsigned int right_bit_count = n - bits_left_; unsigned int right_bit_count = n - bits_left_;
unsigned int left = bits >> right_bit_count; unsigned int left = bits >> right_bit_count;
push_bits_unchecked(left, bits_left_, (1 << bits_left_) - 1); push_bits_unchecked(left, bits_left_, (1 << bits_left_) - 1);
push_bits_unchecked(bits, right_bit_count, (1 << right_bit_count) - 1); push_bits_unchecked(bits, right_bit_count, (1 << right_bit_count) - 1);
} }
void flush() void flush()
{ {
if (bits_left_ == max_bits) if (bits_left_ == max_bits)
return; return;
cur_ <<= bits_left_; cur_ <<= bits_left_;
self().push_data(cur_); self().push_data(cur_);
} }
protected: protected:
Self& self() Self& self()
{ {
return static_cast<Self&>(*this); return static_cast<Self&>(*this);
} }
const Self& self() const const Self& self() const
{ {
return static_cast<const Self&>(*this); return static_cast<const Self&>(*this);
} }
unsigned int cur_; unsigned int cur_;
@ -189,41 +189,41 @@ namespace spot
{ {
public: public:
int_array_vector_compression(const int* array, size_t n) int_array_vector_compression(const int* array, size_t n)
: array_(array), n_(n), pos_(0), result_(new std::vector<unsigned int>) : array_(array), n_(n), pos_(0), result_(new std::vector<unsigned int>)
{ {
} }
void push_data(unsigned int i) void push_data(unsigned int i)
{ {
result_->push_back(i); result_->push_back(i);
} }
const std::vector<unsigned int>* const std::vector<unsigned int>*
result() const result() const
{ {
return result_; return result_;
} }
bool have_data() const bool have_data() const
{ {
return pos_ < n_; return pos_ < n_;
} }
unsigned int next_data() unsigned int next_data()
{ {
return static_cast<unsigned int>(array_[pos_++]); return static_cast<unsigned int>(array_[pos_++]);
} }
bool skip_if(unsigned int val) bool skip_if(unsigned int val)
{ {
if (SPOT_UNLIKELY(!have_data())) if (SPOT_UNLIKELY(!have_data()))
return false; return false;
if (static_cast<unsigned int>(array_[pos_]) != val) if (static_cast<unsigned int>(array_[pos_]) != val)
return false; return false;
++pos_; ++pos_;
return true; return true;
} }
protected: protected:
@ -238,36 +238,36 @@ namespace spot
{ {
public: public:
int_vector_vector_compression(const std::vector<int>& input, int_vector_vector_compression(const std::vector<int>& input,
std::vector<unsigned int>& output) std::vector<unsigned int>& output)
: input_(input), pos_(input.begin()), end_(input.end()), output_(output) : input_(input), pos_(input.begin()), end_(input.end()), output_(output)
{ {
} }
void push_data(unsigned int i) void push_data(unsigned int i)
{ {
output_.push_back(i); output_.push_back(i);
} }
bool have_data() const bool have_data() const
{ {
return pos_ < end_; return pos_ < end_;
} }
unsigned int next_data() unsigned int next_data()
{ {
return static_cast<unsigned int>(*pos_++); return static_cast<unsigned int>(*pos_++);
} }
bool skip_if(unsigned int val) bool skip_if(unsigned int val)
{ {
if (SPOT_UNLIKELY(!have_data())) if (SPOT_UNLIKELY(!have_data()))
return false; return false;
if (static_cast<unsigned int>(*pos_) != val) if (static_cast<unsigned int>(*pos_) != val)
return false; return false;
++pos_; ++pos_;
return true; return true;
} }
protected: protected:
@ -282,40 +282,40 @@ namespace spot
{ {
public: public:
int_array_array_compression(const int* array, size_t n, int_array_array_compression(const int* array, size_t n,
int* dest, size_t& dest_n) int* dest, size_t& dest_n)
: array_(array), n_(n), pos_(0), : array_(array), n_(n), pos_(0),
result_size_(dest_n), result_(dest), result_end_(dest + dest_n) 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) void push_data(unsigned int i)
{ {
assert(result_ < result_end_); assert(result_ < result_end_);
++result_size_; ++result_size_;
*result_++ = static_cast<int>(i); *result_++ = static_cast<int>(i);
} }
bool have_data() const bool have_data() const
{ {
return pos_ < n_; return pos_ < n_;
} }
unsigned int next_data() unsigned int next_data()
{ {
return static_cast<unsigned int>(array_[pos_++]); return static_cast<unsigned int>(array_[pos_++]);
} }
bool skip_if(unsigned int val) bool skip_if(unsigned int val)
{ {
if (SPOT_UNLIKELY(!have_data())) if (SPOT_UNLIKELY(!have_data()))
return false; return false;
if (static_cast<unsigned int>(array_[pos_]) != val) if (static_cast<unsigned int>(array_[pos_]) != val)
return false; return false;
++pos_; ++pos_;
return true; return true;
} }
protected: protected:
@ -330,7 +330,7 @@ namespace spot
void void
int_vector_vector_compress(const std::vector<int>& input, int_vector_vector_compress(const std::vector<int>& input,
std::vector<unsigned>& output) std::vector<unsigned>& output)
{ {
int_vector_vector_compression c(input, output); int_vector_vector_compression c(input, output);
c.run(); c.run();
@ -346,7 +346,7 @@ namespace spot
void void
int_array_array_compress(const int* array, size_t n, 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); int_array_array_compression c(array, n, dest, dest_size);
c.run(); c.run();
@ -365,154 +365,154 @@ namespace spot
public: public:
void refill() void refill()
{ {
if (SPOT_UNLIKELY(look_bits_ == 0)) if (SPOT_UNLIKELY(look_bits_ == 0))
{ {
look_bits_ = max_bits; look_bits_ = max_bits;
look_ = buffer_; look_ = buffer_;
if (SPOT_LIKELY(self().have_comp_data())) if (SPOT_LIKELY(self().have_comp_data()))
buffer_ = self().next_comp_data(); buffer_ = self().next_comp_data();
if (SPOT_LIKELY(buffer_bits_ != max_bits)) if (SPOT_LIKELY(buffer_bits_ != max_bits))
{ {
unsigned int fill_size = max_bits - buffer_bits_; unsigned int fill_size = max_bits - buffer_bits_;
look_ <<= fill_size; look_ <<= fill_size;
look_ |= buffer_ >> buffer_bits_; look_ |= buffer_ >> buffer_bits_;
} }
} }
else else
{ {
unsigned int fill_size = max_bits - look_bits_; unsigned int fill_size = max_bits - look_bits_;
if (fill_size > buffer_bits_) if (fill_size > buffer_bits_)
fill_size = buffer_bits_; fill_size = buffer_bits_;
look_ <<= fill_size; look_ <<= fill_size;
buffer_bits_ -= fill_size; buffer_bits_ -= fill_size;
look_ |= (buffer_ >> buffer_bits_) & ((1 << fill_size) - 1); look_ |= (buffer_ >> buffer_bits_) & ((1 << fill_size) - 1);
look_bits_ += fill_size; look_bits_ += fill_size;
if (buffer_bits_ == 0) if (buffer_bits_ == 0)
{ {
if (SPOT_LIKELY(self().have_comp_data())) if (SPOT_LIKELY(self().have_comp_data()))
buffer_ = self().next_comp_data(); buffer_ = self().next_comp_data();
unsigned int left = max_bits - look_bits_; unsigned int left = max_bits - look_bits_;
if (left != 0) if (left != 0)
{ {
look_ <<= left; look_ <<= left;
look_ |= buffer_ >> look_bits_; look_ |= buffer_ >> look_bits_;
buffer_bits_ = look_bits_; buffer_bits_ = look_bits_;
look_bits_ = max_bits; look_bits_ = max_bits;
} }
else else
{ {
buffer_bits_ = max_bits; buffer_bits_ = max_bits;
} }
} }
} }
} }
unsigned int look_n_bits(unsigned int n) unsigned int look_n_bits(unsigned int n)
{ {
if (SPOT_UNLIKELY(look_bits_ < n)) if (SPOT_UNLIKELY(look_bits_ < n))
refill(); refill();
assert(n <= look_bits_); assert(n <= look_bits_);
return (look_ >> (look_bits_ - n)) & ((1 << n) - 1); return (look_ >> (look_bits_ - n)) & ((1 << n) - 1);
} }
void skip_n_bits(unsigned int n) void skip_n_bits(unsigned int n)
{ {
assert (n <= look_bits_); assert (n <= look_bits_);
look_bits_ -= n; look_bits_ -= n;
} }
unsigned int get_n_bits(unsigned int n) unsigned int get_n_bits(unsigned int n)
{ {
if (SPOT_UNLIKELY(look_bits_ < n)) if (SPOT_UNLIKELY(look_bits_ < n))
refill(); refill();
look_bits_ -= n; look_bits_ -= n;
return (look_ >> look_bits_) & ((1 << n) - 1); return (look_ >> look_bits_) & ((1 << n) - 1);
} }
unsigned int get_32_bits() unsigned int get_32_bits()
{ {
// std::cerr << "get_32" << std::endl; // std::cerr << "get_32" << std::endl;
if (SPOT_LIKELY(look_bits_ < 32)) if (SPOT_LIKELY(look_bits_ < 32))
refill(); refill();
unsigned int val = look_; unsigned int val = look_;
look_bits_ = 0; look_bits_ = 0;
refill(); refill();
return val; return val;
} }
void run() void run()
{ {
if (SPOT_UNLIKELY(!self().have_comp_data())) if (SPOT_UNLIKELY(!self().have_comp_data()))
return; return;
look_ = self().next_comp_data(); look_ = self().next_comp_data();
look_bits_ = max_bits; look_bits_ = max_bits;
if (SPOT_LIKELY(self().have_comp_data())) if (SPOT_LIKELY(self().have_comp_data()))
{ {
buffer_ = self().next_comp_data(); buffer_ = self().next_comp_data();
buffer_bits_ = max_bits; buffer_bits_ = max_bits;
} }
else else
{ {
buffer_ = 0; buffer_ = 0;
buffer_bits_ = 0; buffer_bits_ = 0;
} }
while (SPOT_LIKELY(!self().complete())) while (SPOT_LIKELY(!self().complete()))
{ {
unsigned int token = look_n_bits(3); unsigned int token = look_n_bits(3);
switch (token) switch (token)
{ {
case 0x0: // 00[0] case 0x0: // 00[0]
case 0x1: // 00[1] case 0x1: // 00[1]
skip_n_bits(2); skip_n_bits(2);
self().push_data(0); self().push_data(0);
break; break;
case 0x2: // 010 case 0x2: // 010
skip_n_bits(3); skip_n_bits(3);
self().push_data(1); self().push_data(1);
break; break;
case 0x3: // 011 case 0x3: // 011
skip_n_bits(3); skip_n_bits(3);
self().push_data(2 + get_n_bits(2)); self().push_data(2 + get_n_bits(2));
break; break;
case 0x4: // 100 case 0x4: // 100
skip_n_bits(3); skip_n_bits(3);
self().push_data(6 + get_n_bits(4)); self().push_data(6 + get_n_bits(4));
break; break;
case 0x5: // 101 case 0x5: // 101
skip_n_bits(3); skip_n_bits(3);
self().repeat(1 + get_n_bits(3)); self().repeat(1 + get_n_bits(3));
break; break;
case 0x6: // 110 case 0x6: // 110
skip_n_bits(3); skip_n_bits(3);
self().repeat(9 + get_n_bits(5)); self().repeat(9 + get_n_bits(5));
break; break;
case 0x7: // 111 case 0x7: // 111
skip_n_bits(3); skip_n_bits(3);
self().push_data(get_32_bits()); self().push_data(get_32_bits());
break; break;
default: default:
SPOT_UNREACHABLE(); SPOT_UNREACHABLE();
} }
} }
} }
protected: protected:
Self& self() Self& self()
{ {
return static_cast<Self&>(*this); return static_cast<Self&>(*this);
} }
const Self& self() const const Self& self() const
{ {
return static_cast<const Self&>(*this); return static_cast<const Self&>(*this);
} }
unsigned int look_; unsigned int look_;
@ -526,41 +526,41 @@ namespace spot
{ {
public: public:
int_vector_vector_decompression(const std::vector<unsigned int>& array, int_vector_vector_decompression(const std::vector<unsigned int>& array,
std::vector<int>& res, size_t size) std::vector<int>& res, size_t size)
: prev_(0), array_(array), : prev_(0), array_(array),
pos_(array.begin()), end_(array.end()), pos_(array.begin()), end_(array.end()),
result_(res), size_(size) result_(res), size_(size)
{ {
result_.reserve(size); result_.reserve(size);
} }
bool complete() const bool complete() const
{ {
return size_ == 0; return size_ == 0;
} }
void push_data(int i) void push_data(int i)
{ {
prev_ = i; prev_ = i;
result_.push_back(i); result_.push_back(i);
--size_; --size_;
} }
void repeat(unsigned int i) void repeat(unsigned int i)
{ {
size_ -= i; size_ -= i;
while (i--) while (i--)
result_.push_back(prev_); result_.push_back(prev_);
} }
bool have_comp_data() const bool have_comp_data() const
{ {
return pos_ != end_; return pos_ != end_;
} }
unsigned int next_comp_data() unsigned int next_comp_data()
{ {
return *pos_++; return *pos_++;
} }
protected: protected:
@ -577,40 +577,40 @@ namespace spot
{ {
public: public:
int_vector_array_decompression(const std::vector<unsigned int>* array, int_vector_array_decompression(const std::vector<unsigned int>* array,
int* res, int* res,
size_t size) size_t size)
: prev_(0), array_(array), n_(array->size()), pos_(0), result_(res), : prev_(0), array_(array), n_(array->size()), pos_(0), result_(res),
size_(size) size_(size)
{ {
} }
bool complete() const bool complete() const
{ {
return size_ == 0; return size_ == 0;
} }
void push_data(int i) void push_data(int i)
{ {
prev_ = i; prev_ = i;
*result_++ = i; *result_++ = i;
--size_; --size_;
} }
void repeat(unsigned int i) void repeat(unsigned int i)
{ {
size_ -= i; size_ -= i;
while (i--) while (i--)
*result_++ = prev_; *result_++ = prev_;
} }
bool have_comp_data() const bool have_comp_data() const
{ {
return pos_ < n_; return pos_ < n_;
} }
unsigned int next_comp_data() unsigned int next_comp_data()
{ {
return (*array_)[pos_++]; return (*array_)[pos_++];
} }
protected: protected:
@ -627,41 +627,41 @@ namespace spot
{ {
public: public:
int_array_array_decompression(const int* array, int_array_array_decompression(const int* array,
size_t array_size, size_t array_size,
int* res, int* res,
size_t size) size_t size)
: prev_(0), array_(array), n_(array_size), pos_(0), result_(res), : prev_(0), array_(array), n_(array_size), pos_(0), result_(res),
size_(size) size_(size)
{ {
} }
bool complete() const bool complete() const
{ {
return size_ == 0; return size_ == 0;
} }
void push_data(int i) void push_data(int i)
{ {
prev_ = i; prev_ = i;
*result_++ = i; *result_++ = i;
--size_; --size_;
} }
void repeat(unsigned int i) void repeat(unsigned int i)
{ {
size_ -= i; size_ -= i;
while (i--) while (i--)
*result_++ = prev_; *result_++ = prev_;
} }
bool have_comp_data() const bool have_comp_data() const
{ {
return pos_ < n_; return pos_ < n_;
} }
unsigned int next_comp_data() unsigned int next_comp_data()
{ {
return array_[pos_++]; return array_[pos_++];
} }
protected: protected:
@ -677,7 +677,7 @@ namespace spot
void void
int_vector_vector_decompress(const std::vector<unsigned int>& input, int_vector_vector_decompress(const std::vector<unsigned int>& input,
std::vector<int>& output, size_t size) std::vector<int>& output, size_t size)
{ {
int_vector_vector_decompression c(input, output, size); int_vector_vector_decompression c(input, output, size);
c.run(); c.run();
@ -685,7 +685,7 @@ namespace spot
void void
int_vector_array_decompress(const std::vector<unsigned int>* array, int* res, int_vector_array_decompress(const std::vector<unsigned int>* array, int* res,
size_t size) size_t size)
{ {
int_vector_array_decompression c(array, res, size); int_vector_array_decompression c(array, res, size);
c.run(); c.run();
@ -693,7 +693,7 @@ namespace spot
void void
int_array_array_decompress(const int* array, size_t array_size, 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); int_array_array_decompression c(array, array_size, res, size);
c.run(); c.run();

View file

@ -31,7 +31,7 @@ namespace spot
/// Compress an int vector into a vector of unsigned int. /// Compress an int vector into a vector of unsigned int.
SPOT_API void SPOT_API void
int_vector_vector_compress(const std::vector<int>& input, int_vector_vector_compress(const std::vector<int>& input,
std::vector<unsigned int>& output); std::vector<unsigned int>& output);
/// \brief Uncompress a vector of unsigned int into a vector of /// \brief Uncompress a vector of unsigned int into a vector of
/// size \a size. /// size \a size.
@ -39,7 +39,7 @@ namespace spot
/// \a size must be the exact expected size of uncompressed array. /// \a size must be the exact expected size of uncompressed array.
SPOT_API void SPOT_API void
int_vector_vector_decompress(const std::vector<unsigned int>& array, int_vector_vector_decompress(const std::vector<unsigned int>& array,
std::vector<int>& output, size_t size); std::vector<int>& output, size_t size);
/// Compress an int array if size \a n into a vector of unsigned int. /// Compress an int array if size \a n into a vector of unsigned int.
SPOT_API const std::vector<unsigned int>* SPOT_API const std::vector<unsigned int>*
@ -51,7 +51,7 @@ namespace spot
/// \a size must be the exact expected size of uncompressed array. /// \a size must be the exact expected size of uncompressed array.
SPOT_API void SPOT_API void
int_vector_array_decompress(const std::vector<unsigned int>* array, int_vector_array_decompress(const std::vector<unsigned int>* array,
int* res, size_t size); int* res, size_t size);
/// \brief Compress an int array of size \a n into a int array. /// \brief Compress an int array of size \a n into a int array.
/// ///
@ -61,7 +61,7 @@ namespace spot
/// filled in \a dest /// filled in \a dest
SPOT_API void SPOT_API void
int_array_array_compress(const int* array, size_t n, 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 /// \brief Uncompress an int array of size \a array_size into a int
/// array of size \a size. /// array of size \a size.
@ -69,7 +69,7 @@ namespace spot
/// \a size must be the exact expected size of uncompressed array. /// \a size must be the exact expected size of uncompressed array.
SPOT_API void SPOT_API void
int_array_array_decompress(const int* array, size_t array_size, int_array_array_decompress(const int* array, size_t array_size,
int* res, size_t size); int* res, size_t size);
/// @} /// @}
} }

View file

@ -157,8 +157,8 @@ namespace spot
position last = loc.end - 1; position last = loc.end - 1;
ostr << loc.begin; ostr << loc.begin;
if (last.filename if (last.filename
&& (!loc.begin.filename && (!loc.begin.filename
|| *loc.begin.filename != *last.filename)) || *loc.begin.filename != *last.filename))
ostr << '-' << last; ostr << '-' << last;
else if (loc.begin.line != last.line) else if (loc.begin.line != last.line)
ostr << '-' << last.line << '.' << last.column; ostr << '-' << last.line << '.' << last.column;

View file

@ -51,12 +51,12 @@ namespace spot
{ {
if (input_min == input_max) if (input_min == input_max)
{ {
cube_.push(bdd_satprefix(input_min)); cube_.push(bdd_satprefix(input_min));
input_max = input_min; input_max = input_min;
} }
else else
{ {
cube_.push(bddtrue); cube_.push(bddtrue);
} }
bdd common = input_min & input_max; bdd common = input_min & input_max;
todo_.emplace(input_min, input_max, bdd_support(common)); todo_.emplace(input_min, input_max, bdd_support(common));
@ -67,110 +67,110 @@ namespace spot
{ {
while (!todo_.empty()) while (!todo_.empty())
{ {
local_vars& l = todo_.top(); local_vars& l = todo_.top();
switch (l.step) switch (l.step)
{ {
case local_vars::FirstStep: case local_vars::FirstStep:
next_var: next_var:
{ {
if (l.f_min == bddfalse) if (l.f_min == bddfalse)
{ {
ret_ = bddfalse; ret_ = bddfalse;
todo_.pop(); todo_.pop();
continue; continue;
} }
if (l.vars == bddtrue || l.f_max == bddtrue) if (l.vars == bddtrue || l.f_max == bddtrue)
{ {
ret_ = l.f_max; ret_ = l.f_max;
todo_.pop(); todo_.pop();
return cube_.top() & ret_; return cube_.top() & ret_;
} }
assert(l.vars != bddfalse); assert(l.vars != bddfalse);
// Pick the first variable in VARS that is used by F_MIN // 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 // or F_MAX. We know that VARS, F_MIN or F_MAX are not
// constants (bddtrue or bddfalse) because one of the // constants (bddtrue or bddfalse) because one of the
// two above `if' would have matched; so it's ok to call // two above `if' would have matched; so it's ok to call
// bdd_var(). // bdd_var().
int v = bdd_var(l.vars); int v = bdd_var(l.vars);
l.vars = bdd_high(l.vars); l.vars = bdd_high(l.vars);
int v_min = bdd_var(l.f_min); int v_min = bdd_var(l.f_min);
int v_max = bdd_var(l.f_max); int v_max = bdd_var(l.f_max);
if (v < v_min && v < v_max) if (v < v_min && v < v_max)
// Do not use a while() for this goto, because we want // Do not use a while() for this goto, because we want
// `continue' to be relative to the outermost while(). // `continue' to be relative to the outermost while().
goto next_var; goto next_var;
l.step = local_vars::SecondStep; l.step = local_vars::SecondStep;
bdd v0 = bdd_nithvar(v); bdd v0 = bdd_nithvar(v);
l.v1 = bdd_ithvar(v); l.v1 = bdd_ithvar(v);
// All the following should be equivalent to // All the following should be equivalent to
// f0_min = bdd_restrict(f_min, v0); // f0_min = bdd_restrict(f_min, v0);
// f0_max = bdd_restrict(f_max, v0); // f0_max = bdd_restrict(f_max, v0);
// f1_min = bdd_restrict(f_min, v1); // f1_min = bdd_restrict(f_min, v1);
// f1_max = bdd_restrict(f_max, v1); // f1_max = bdd_restrict(f_max, v1);
// but we try to avoid bdd_restrict when possible. // but we try to avoid bdd_restrict when possible.
if (v == v_min) if (v == v_min)
{ {
l.f0_min = bdd_low(l.f_min); l.f0_min = bdd_low(l.f_min);
l.f1_min = bdd_high(l.f_min); l.f1_min = bdd_high(l.f_min);
} }
else if (v_min < v) else if (v_min < v)
{ {
l.f0_min = bdd_restrict(l.f_min, v0); l.f0_min = bdd_restrict(l.f_min, v0);
l.f1_min = bdd_restrict(l.f_min, l.v1); l.f1_min = bdd_restrict(l.f_min, l.v1);
} }
else else
{ {
l.f1_min = l.f0_min = l.f_min; l.f1_min = l.f0_min = l.f_min;
} }
if (v == v_max) if (v == v_max)
{ {
l.f0_max = bdd_low(l.f_max); l.f0_max = bdd_low(l.f_max);
l.f1_max = bdd_high(l.f_max); l.f1_max = bdd_high(l.f_max);
} }
else if (v_max < v) else if (v_max < v)
{ {
l.f0_max = bdd_restrict(l.f_max, v0); l.f0_max = bdd_restrict(l.f_max, v0);
l.f1_max = bdd_restrict(l.f_max, l.v1); l.f1_max = bdd_restrict(l.f_max, l.v1);
} }
else else
{ {
l.f1_max = l.f0_max = l.f_max; l.f1_max = l.f0_max = l.f_max;
} }
cube_.push(cube_.top() & v0); cube_.push(cube_.top() & v0);
todo_.emplace(l.f0_min - l.f1_max, l.f0_max, l.vars); todo_.emplace(l.f0_min - l.f1_max, l.f0_max, l.vars);
} }
continue; continue;
case local_vars::SecondStep: case local_vars::SecondStep:
l.step = local_vars::ThirdStep; l.step = local_vars::ThirdStep;
l.g0 = ret_; l.g0 = ret_;
cube_.pop(); cube_.pop();
cube_.push(cube_.top() & l.v1); cube_.push(cube_.top() & l.v1);
todo_.emplace(l.f1_min - l.f0_max, l.f1_max, l.vars); todo_.emplace(l.f1_min - l.f0_max, l.f1_max, l.vars);
continue; continue;
case local_vars::ThirdStep: case local_vars::ThirdStep:
l.step = local_vars::FourthStep; l.step = local_vars::FourthStep;
l.g1 = ret_; l.g1 = ret_;
cube_.pop(); cube_.pop();
{ {
bdd fs_max = l.f0_max & l.f1_max; bdd fs_max = l.f0_max & l.f1_max;
bdd fs_min = fs_max & ((l.f0_min - l.g0) | (l.f1_min - l.g1)); bdd fs_min = fs_max & ((l.f0_min - l.g0) | (l.f1_min - l.g1));
todo_.emplace(fs_min, fs_max, l.vars); todo_.emplace(fs_min, fs_max, l.vars);
} }
continue; continue;
case local_vars::FourthStep: case local_vars::FourthStep:
ret_ |= (l.g0 - l.v1) | (l.g1 & l.v1); ret_ |= (l.g0 - l.v1) | (l.g1 & l.v1);
todo_.pop(); todo_.pop();
continue; continue;
} }
SPOT_UNREACHABLE(); SPOT_UNREACHABLE();
} }
return bddfalse; return bddfalse;
} }

View file

@ -91,7 +91,7 @@ namespace spot
bdd f1_min, f1_max; bdd f1_min, f1_max;
bdd g0, g1; bdd g0, g1;
local_vars(bdd f_min, bdd f_max, bdd vars) 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<local_vars> todo_; std::stack<local_vars> todo_;
std::stack<bdd> cube_; std::stack<bdd> cube_;

View file

@ -43,17 +43,17 @@ namespace spot
~multiple_size_pool() ~multiple_size_pool()
{ {
while (chunklist_) while (chunklist_)
{ {
chunk_* prev = chunklist_->prev; chunk_* prev = chunklist_->prev;
free(chunklist_); free(chunklist_);
chunklist_ = prev; chunklist_ = prev;
} }
} }
size_t fixsize(size_t size) const size_t fixsize(size_t size) const
{ {
if (size < sizeof(block_)) if (size < sizeof(block_))
size = sizeof(block_); size = sizeof(block_);
return (size + alignment_ - 1) & ~(alignment_ - 1); return (size + alignment_ - 1) & ~(alignment_ - 1);
} }
@ -67,28 +67,28 @@ namespace spot
block_*& f = freelist_[size]; block_*& f = freelist_[size];
// If we have free blocks available, return the first one. // If we have free blocks available, return the first one.
if (f) if (f)
{ {
block_* first = f; block_* first = f;
f = f->next; f = f->next;
return first; return first;
} }
// Else, create a block out of the last chunk of allocated // Else, create a block out of the last chunk of allocated
// memory. // memory.
// If all the last chunk has been used, allocate one more. // If all the last chunk has been used, allocate one more.
if (free_start_ + size > free_end_) if (free_start_ + size > free_end_)
{ {
const size_t requested = (size > 128 ? size : 128) * 8192 - 64; const size_t requested = (size > 128 ? size : 128) * 8192 - 64;
chunk_* c = reinterpret_cast<chunk_*>(malloc(requested)); chunk_* c = reinterpret_cast<chunk_*>(malloc(requested));
if (!c) if (!c)
throw std::bad_alloc(); throw std::bad_alloc();
c->prev = chunklist_; c->prev = chunklist_;
chunklist_ = c; chunklist_ = c;
free_start_ = c->data_ + size; free_start_ = c->data_ + size;
free_end_ = c->data_ + requested; free_end_ = c->data_ + requested;
} }
void* res = free_start_; void* res = free_start_;
free_start_ += size; free_start_ += size;

View file

@ -33,96 +33,96 @@ namespace spot
{ {
while (*options) while (*options)
{ {
// Skip leading separators. // Skip leading separators.
while (*options && strchr(" \t\n,;", *options)) while (*options && strchr(" \t\n,;", *options))
++options; ++options;
// `!foo' is a shorthand for `foo=0'. // `!foo' is a shorthand for `foo=0'.
const char* negated = nullptr; const char* negated = nullptr;
if (*options == '!') if (*options == '!')
{ {
// Skip spaces. // Skip spaces.
while (*options && strchr(" \t\n", *options)) while (*options && strchr(" \t\n", *options))
++options; ++options;
negated = options++; negated = options++;
} }
if (!*options) if (!*options)
{ {
if (negated) if (negated)
return negated; return negated;
else else
break; break;
} }
const char* name_start = options; const char* name_start = options;
// Find the end of the name. // Find the end of the name.
while (*options && !strchr(", \t\n;=", *options)) while (*options && !strchr(", \t\n;=", *options))
++options; ++options;
std::string name(name_start, options); std::string name(name_start, options);
// Skip spaces. // Skip spaces.
while (*options && strchr(" \t\n", *options)) while (*options && strchr(" \t\n", *options))
++options; ++options;
if (*options != '=') if (*options != '=')
{ {
options_[name] = (negated ? 0 : 1); options_[name] = (negated ? 0 : 1);
} }
else if (negated) else if (negated)
{ {
return negated; return negated;
} }
else else
{ {
++options; ++options;
// Skip spaces. // Skip spaces.
while (*options && strchr(" \t\n", *options)) while (*options && strchr(" \t\n", *options))
++options; ++options;
if (!*options) if (!*options)
return name_start; return name_start;
if (*options == '\'' || *options == '"') if (*options == '\'' || *options == '"')
{ {
auto sep = *options; auto sep = *options;
auto start = options + 1; auto start = options + 1;
do do
++options; ++options;
while (*options && *options != sep); while (*options && *options != sep);
if (*options != sep) if (*options != sep)
return start - 1; return start - 1;
std::string val(start, options); std::string val(start, options);
options_str_[name] = val; options_str_[name] = val;
if (*options) if (*options)
++options; ++options;
} }
else else
{ {
char* val_end; char* val_end;
int val = strtol(options, &val_end, 10); int val = strtol(options, &val_end, 10);
if (val_end == options) if (val_end == options)
return name_start; return name_start;
if (*val_end == 'K') if (*val_end == 'K')
{ {
val *= 1024; val *= 1024;
++val_end; ++val_end;
} }
else if (*val_end == 'M') else if (*val_end == 'M')
{ {
val *= 1024 * 1024; val *= 1024 * 1024;
++val_end; ++val_end;
} }
else if (*val_end && !strchr(" \t\n,;", *val_end)) else if (*val_end && !strchr(" \t\n,;", *val_end))
{ {
return options; return options;
} }
options = val_end; options = val_end;
options_[name] = val; options_[name] = val;
} }
} }
} }
return nullptr; return nullptr;
} }

View file

@ -84,7 +84,7 @@ namespace spot
/// \return The previous value associated to \a option if declared, /// \return The previous value associated to \a option if declared,
/// or \a def otherwise. /// or \a def otherwise.
std::string set_str(const char* option, 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. /// Acquire all the settings of \a o.
void set(const option_map& o); void set(const option_map& o);

View file

@ -96,8 +96,8 @@ namespace spot
if (has_next) if (has_next)
{ {
has_next = false; has_next = false;
return next; return next;
} }
double x; double x;
@ -105,9 +105,9 @@ namespace spot
double r; double r;
do do
{ {
x = 2.0 * drand() - 1.0; x = 2.0 * drand() - 1.0;
y = 2.0 * drand() - 1.0; y = 2.0 * drand() - 1.0;
r = x * x + y * y; r = x * x + y * y;
} }
while (r >= 1.0 || r == 0.0); while (r >= 1.0 || r == 0.0);
r = sqrt(-2 * log(r) / r); r = sqrt(-2 * log(r) / r);
@ -124,8 +124,8 @@ namespace spot
while (s < p) while (s < p)
{ {
s -= log(1.0 - drand()); s -= log(1.0 - drand());
++x; ++x;
} }
return x - 1; return x - 1;
} }

View file

@ -97,12 +97,12 @@ namespace spot
rand() const rand() const
{ {
for (;;) for (;;)
{ {
int x = round(gen() * s_ + m_); int x = round(gen() * s_ + m_);
if (x < 0) if (x < 0)
continue; continue;
if (x <= n_) if (x <= n_)
return x; return x;
} }
SPOT_UNREACHABLE(); SPOT_UNREACHABLE();
return 0; return 0;
@ -128,11 +128,11 @@ namespace spot
auto d = std::distance(first, last); auto d = std::distance(first, last);
if (d > 1) if (d > 1)
{ {
for (--last; first < last; ++first, --d) for (--last; first < last; ++first, --d)
{ {
auto i = mrand(d); auto i = mrand(d);
std::swap(*first, *(first + i)); std::swap(*first, *(first + i));
} }
} }
} }
/// @} /// @}

View file

@ -37,48 +37,48 @@ namespace spot
satsolver_command() satsolver_command()
{ {
satsolver = getenv("SPOT_SATSOLVER"); satsolver = getenv("SPOT_SATSOLVER");
if (!satsolver) if (!satsolver)
{ {
satsolver = "glucose -verb=0 -model %I >%O"; satsolver = "glucose -verb=0 -model %I >%O";
return; return;
} }
prime(satsolver); prime(satsolver);
if (!has('I')) if (!has('I'))
throw std::runtime_error("SPOT_SATSOLVER should contain %I to " throw std::runtime_error("SPOT_SATSOLVER should contain %I to "
"indicate how to use the input filename."); "indicate how to use the input filename.");
if (!has('O')) if (!has('O'))
throw std::runtime_error("SPOT_SATSOLVER should contain %O to " throw std::runtime_error("SPOT_SATSOLVER should contain %O to "
"indicate how to use the output filename."); "indicate how to use the output filename.");
} }
int int
run(printable* in, printable* out) run(printable* in, printable* out)
{ {
declare('I', in); declare('I', in);
declare('O', out); declare('O', out);
std::ostringstream s; std::ostringstream s;
format(s, satsolver); format(s, satsolver);
int res = system(s.str().c_str()); int res = system(s.str().c_str());
if (res < 0 || (WIFEXITED(res) && WEXITSTATUS(res) == 127)) if (res < 0 || (WIFEXITED(res) && WEXITSTATUS(res) == 127))
{ {
s << ": failed to execute"; s << ": failed to execute";
throw std::runtime_error(s.str()); throw std::runtime_error(s.str());
} }
// For POSIX shells, "The exit status of a command that // For POSIX shells, "The exit status of a command that
// terminated because it received a signal shall be reported // terminated because it received a signal shall be reported
// as greater than 128." // as greater than 128."
if (WIFEXITED(res) && WEXITSTATUS(res) >= 128) if (WIFEXITED(res) && WEXITSTATUS(res) >= 128)
{ {
s << ": terminated by signal"; s << ": terminated by signal";
throw std::runtime_error(s.str()); throw std::runtime_error(s.str());
} }
if (WIFSIGNALED(res)) if (WIFSIGNALED(res))
{ {
s << ": terminated by signal " << WTERMSIG(res); s << ": terminated by signal " << WTERMSIG(res);
throw std::runtime_error(s.str()); throw std::runtime_error(s.str());
} }
return res; return res;
} }
}; };
} }
@ -96,25 +96,25 @@ namespace spot
int c; int c;
while ((c = in->get()) != EOF) while ((c = in->get()) != EOF)
{ {
// If a line does not start with 'v ', ignore it. // If a line does not start with 'v ', ignore it.
if (c != 'v' || in->get() != ' ') if (c != 'v' || in->get() != ' ')
{ {
in->ignore(std::numeric_limits<std::streamsize>::max(), '\n'); in->ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue; continue;
} }
// Otherwise, read integers one by one. // Otherwise, read integers one by one.
int i; int i;
while (*in >> i) while (*in >> i)
{ {
if (i == 0) if (i == 0)
goto done; goto done;
sol.push_back(i); sol.push_back(i);
} }
if (!in->eof()) if (!in->eof())
// If we haven't reached end-of-file, then we just attempted // If we haven't reached end-of-file, then we just attempted
// to extract something that wasn't an integer. Clear the // to extract something that wasn't an integer. Clear the
// fail bit so that will loop over. // fail bit so that will loop over.
in->clear(); in->clear();
} }
done: done:
if (in != &std::cin) if (in != &std::cin)
@ -149,7 +149,7 @@ namespace spot
satsolver::solution_pair satsolver::solution_pair
satsolver::get_solution() satsolver::get_solution()
{ {
delete cnf_stream_; // Close the file. delete cnf_stream_; // Close the file.
cnf_stream_ = nullptr; cnf_stream_ = nullptr;
temporary_file* output = create_tmpfile("sat-", ".out"); temporary_file* output = create_tmpfile("sat-", ".out");

View file

@ -43,7 +43,7 @@ namespace spot
void check() const void check() const
{ {
if (count_ < 0) 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++() clause_counter& operator++()

View file

@ -37,8 +37,8 @@ namespace spot
time_info total; time_info total;
for (tm_type::const_iterator i = tm.begin(); i != tm.end(); ++i) for (tm_type::const_iterator i = tm.begin(); i != tm.end(); ++i)
{ {
total.utime += i->second.first.utime(); total.utime += i->second.first.utime();
total.stime += i->second.first.stime(); total.stime += i->second.first.stime();
} }
clock_t grand_total = total.utime + total.stime; clock_t grand_total = total.utime + total.stime;
@ -52,30 +52,30 @@ namespace spot
<< std::endl; << std::endl;
for (tm_type::const_iterator i = tm.begin(); i != tm.end(); ++i) for (tm_type::const_iterator i = tm.begin(); i != tm.end(); ++i)
{ {
// truncate long keys // truncate long keys
std::string name = i->first; std::string name = i->first;
if (name.size() > 22) if (name.size() > 22)
name.erase(22); name.erase(22);
const spot::timer& t = i->second.first; const spot::timer& t = i->second.first;
const char* sep = t.is_running() ? "+|" : " |"; const char* sep = t.is_running() ? "+|" : " |";
os << std::setw(22) << name << sep os << std::setw(22) << name << sep
<< std::setw(6) << t.utime() << ' ' << std::setw(6) << t.utime() << ' '
<< std::setw(8) << (total.utime ? << std::setw(8) << (total.utime ?
100.0 * t.utime() / total.utime : 0.) 100.0 * t.utime() / total.utime : 0.)
<< sep << sep
<< std::setw(6) << t.stime() << ' ' << std::setw(6) << t.stime() << ' '
<< std::setw(8) << (total.stime ? << std::setw(8) << (total.stime ?
100.0 * t.stime() / total.stime : 0.) 100.0 * t.stime() / total.stime : 0.)
<< sep << sep
<< std::setw(6) << t.utime() + t.stime() << ' ' << std::setw(6) << t.utime() + t.stime() << ' '
<< std::setw(8) << (grand_total ? << std::setw(8) << (grand_total ?
(100.0 * (t.utime() + t.stime()) / (100.0 * (t.utime() + t.stime()) /
grand_total) : 0.) grand_total) : 0.)
<< sep << sep
<< std::setw(4) << i->second.second << std::setw(4) << i->second.second
<< std::endl; << std::endl;
} }
os << std::setw(79) << std::setfill('-') << "" << std::setfill(' ') os << std::setw(79) << std::setfill('-') << "" << std::setfill(' ')
<< std::endl << std::endl

View file

@ -197,7 +197,7 @@ namespace spot
assert(i != tm.end()); assert(i != tm.end());
assert(0 < i->second.second); assert(0 < i->second.second);
if (0 == --i->second.second) if (0 == --i->second.second)
tm.erase(i); tm.erase(i);
} }
/// Return the timer \a name. /// Return the timer \a name.

View file

@ -35,14 +35,14 @@ namespace spot
{ {
const char* res = secure_getenv("SPOT_TMPDIR"); const char* res = secure_getenv("SPOT_TMPDIR");
if (res) if (res)
return res; return res;
return secure_getenv("TMPDIR"); return secure_getenv("TMPDIR");
} }
static int static int
create_temporary_file(const char* prefix, create_temporary_file(const char* prefix,
const char* suffix, const char* suffix,
char** name) char** name)
throw(std::bad_alloc, std::runtime_error) throw(std::bad_alloc, std::runtime_error)
{ {
static const char* tmpdir = get_tmpdir(); static const char* tmpdir = get_tmpdir();
@ -51,30 +51,30 @@ namespace spot
size_t len = strlen(prefix); size_t len = strlen(prefix);
size_t slen = 0; size_t slen = 0;
if (suffix) if (suffix)
len += slen = strlen(suffix); len += slen = strlen(suffix);
char* x = *name = static_cast<char*>(malloc(tmpdirlen + 1 + len + 6 + 1)); char* x = *name = static_cast<char*>(malloc(tmpdirlen + 1 + len + 6 + 1));
if (!x) if (!x)
throw std::bad_alloc(); throw std::bad_alloc();
if (tmpdir) if (tmpdir)
{ {
x = stpcpy(x, tmpdir); x = stpcpy(x, tmpdir);
if (x[-1] != '/') if (x[-1] != '/')
*x++ = '/'; *x++ = '/';
} }
x = stpcpy(x, prefix); x = stpcpy(x, prefix);
x = stpcpy(x, "XXXXXX"); x = stpcpy(x, "XXXXXX");
int fd; int fd;
if (suffix) if (suffix)
{ {
stpcpy(x, suffix); stpcpy(x, suffix);
fd = mkstemps(*name, slen); fd = mkstemps(*name, slen);
} }
else else
{ {
fd = mkstemp(*name); fd = mkstemp(*name);
} }
if (fd < 0) 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; return fd;
} }
} }

View file

@ -113,8 +113,8 @@ namespace spot
constexpr trival operator!() const constexpr trival operator!() const
{ {
return trival((val_ == yes_value) ? no_value : return trival((val_ == yes_value) ? no_value :
(val_ == no_value) ? yes_value : (val_ == no_value) ? yes_value :
maybe_value); maybe_value);
} }
}; };
@ -171,8 +171,8 @@ namespace spot
inline std::ostream& operator<<(std::ostream& os, trival v) inline std::ostream& operator<<(std::ostream& os, trival v)
{ {
return os << ((v.val() == trival::no_value) ? "no" return os << ((v.val() == trival::no_value) ? "no"
: (v.val() == trival::maybe_value) ? "maybe" : (v.val() == trival::maybe_value) ? "maybe"
: "yes"); : "yes");
} }
/// @} /// @}

View file

@ -29,11 +29,11 @@ namespace spot
spot::parse_aut_error_list::iterator it; spot::parse_aut_error_list::iterator it;
for (auto& err : errors) for (auto& err : errors)
{ {
if (!filename.empty() && filename != "-") if (!filename.empty() && filename != "-")
os << filename << ':'; os << filename << ':';
os << err.first << ": "; os << err.first << ": ";
os << err.second << std::endl; os << err.second << std::endl;
printed = true; printed = true;
} }
return printed; return printed;
} }

View file

@ -25,8 +25,8 @@
# define YY_DECL \ # define YY_DECL \
int hoayylex(hoayy::parser::semantic_type *yylval, \ int hoayylex(hoayy::parser::semantic_type *yylval, \
spot::location *yylloc, \ spot::location *yylloc, \
spot::parse_aut_error_list& error_list) spot::parse_aut_error_list& error_list)
YY_DECL; YY_DECL;
namespace spot namespace spot

View file

@ -91,11 +91,11 @@ namespace spot
struct automaton_parser_options final struct automaton_parser_options final
{ {
bool ignore_abort = false; ///< Skip aborted automata bool ignore_abort = false; ///< Skip aborted automata
bool debug = false; ///< Run the parser in debug mode? bool debug = false; ///< Run the parser in debug mode?
bool trust_hoa = true; ///< Trust properties in HOA files bool trust_hoa = true; ///< Trust properties in HOA files
bool raise_errors = false; ///< Raise errors as exceptions. bool raise_errors = false; ///< Raise errors as exceptions.
bool want_kripke = false; ///< Parse as a Kripke structure. bool want_kripke = false; ///< Parse as a Kripke structure.
}; };
/// \brief Parse a stream of automata /// \brief Parse a stream of automata
@ -128,7 +128,7 @@ namespace spot
/// \param filename The file to read from. /// \param filename The file to read from.
/// \param opts Parser options. /// \param opts Parser options.
automaton_stream_parser(const std::string& filename, automaton_stream_parser(const std::string& filename,
automaton_parser_options opts = {}); automaton_parser_options opts = {});
/// \brief Parse from an already opened file descriptor. /// \brief Parse from an already opened file descriptor.
/// ///
@ -136,7 +136,7 @@ namespace spot
/// \param filename What to display in error messages. /// \param filename What to display in error messages.
/// \param opts Parser options. /// \param opts Parser options.
automaton_stream_parser(int fd, const std::string& filename, automaton_stream_parser(int fd, const std::string& filename,
automaton_parser_options opts = {}); automaton_parser_options opts = {});
/// \brief Parse from a buffer /// \brief Parse from a buffer
/// ///
@ -144,8 +144,8 @@ namespace spot
/// \param filename What to display in error messages. /// \param filename What to display in error messages.
/// \param opts Parser options. /// \param opts Parser options.
automaton_stream_parser(const char* data, automaton_stream_parser(const char* data,
const std::string& filename, const std::string& filename,
automaton_parser_options opts = {}); automaton_parser_options opts = {});
~automaton_stream_parser(); ~automaton_stream_parser();
@ -165,8 +165,8 @@ namespace spot
/// ///
/// \warning This function is not reentrant. /// \warning This function is not reentrant.
parsed_aut_ptr parse(const bdd_dict_ptr& dict, parsed_aut_ptr parse(const bdd_dict_ptr& dict,
environment& env = environment& env =
default_environment::instance()); default_environment::instance());
}; };
/// \brief Read the first spot::twa_graph from a file. /// \brief Read the first spot::twa_graph from a file.
@ -187,8 +187,8 @@ namespace spot
/// \warning This function is not reentrant. /// \warning This function is not reentrant.
SPOT_API parsed_aut_ptr SPOT_API parsed_aut_ptr
parse_aut(const std::string& filename, parse_aut(const std::string& filename,
const bdd_dict_ptr& dict, const bdd_dict_ptr& dict,
environment& env = default_environment::instance(), environment& env = default_environment::instance(),
automaton_parser_options opts = {}); automaton_parser_options opts = {});
/// @} /// @}
} }

View file

@ -30,7 +30,7 @@ namespace spot
{ {
void void
fix_utf8_locations(const std::string& ltl_string, 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. // LUT to convert byte positions to utf8 positions.
// (The +2 is to account for position 0, not used, // (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 i = b;
std::string::const_iterator e = ltl_string.end(); std::string::const_iterator e = ltl_string.end();
unsigned n = 0; // number of current utf8 character unsigned n = 0; // number of current utf8 character
unsigned prev = 0; // last byte of previous utf8 character unsigned prev = 0; // last byte of previous utf8 character
while (i != e) while (i != e)
{ {
utf8::next(i, e); utf8::next(i, e);
++n; ++n;
unsigned d = std::distance(b, i); unsigned d = std::distance(b, i);
while (prev < d) while (prev < d)
b2u[++prev] = n; b2u[++prev] = n;
} }
b2u[++prev] = ++n; b2u[++prev] = ++n;
@ -58,9 +58,9 @@ namespace spot
parse_error_list::iterator it; parse_error_list::iterator it;
for (it = error_list.begin(); it != error_list.end(); ++it) for (it = error_list.begin(); it != error_list.end(); ++it)
{ {
location& l = it->first; location& l = it->first;
l.begin.column = b2u[l.begin.column]; l.begin.column = b2u[l.begin.column];
l.end.column = b2u[l.end.column]; l.end.column = b2u[l.end.column];
} }
} }
@ -68,45 +68,45 @@ namespace spot
{ {
static bool static bool
format_parse_errors_aux(std::ostream& os, format_parse_errors_aux(std::ostream& os,
const std::string& ltl_string, const std::string& ltl_string,
const parse_error_list& error_list, const parse_error_list& error_list,
unsigned shift) unsigned shift)
{ {
bool printed = false; bool printed = false;
for (auto it: error_list) for (auto it: error_list)
{ {
os << ">>> " << ltl_string << '\n'; os << ">>> " << ltl_string << '\n';
const location& l = it.first; const location& l = it.first;
unsigned n = 1; unsigned n = 1;
for (; n < 4 + l.begin.column + shift; ++n) for (; n < 4 + l.begin.column + shift; ++n)
os << ' '; os << ' ';
// Write at least one '^', even if begin==end. // Write at least one '^', even if begin==end.
os << '^'; os << '^';
++n; ++n;
for (; n < 4 + l.end.column + shift; ++n) for (; n < 4 + l.end.column + shift; ++n)
os << '^'; os << '^';
os << '\n' << it.second << "\n\n"; os << '\n' << it.second << "\n\n";
printed = true; printed = true;
} }
return printed; return printed;
} }
} }
bool bool
parsed_formula::format_errors(std::ostream& os, parsed_formula::format_errors(std::ostream& os,
const std::string& real_input, const std::string& real_input,
unsigned shift) unsigned shift)
{ {
if (utf8::is_valid(input.begin(), input.end())) if (utf8::is_valid(input.begin(), input.end()))
{ {
parse_error_list fixed = errors; parse_error_list fixed = errors;
fix_utf8_locations(input, fixed); fix_utf8_locations(input, fixed);
return format_parse_errors_aux(os, real_input, fixed, shift); return format_parse_errors_aux(os, real_input, fixed, shift);
} }
else else
{ {
return format_parse_errors_aux(os, real_input, errors, shift); return format_parse_errors_aux(os, real_input, errors, shift);
} }
} }

View file

@ -27,8 +27,8 @@
# define YY_DECL \ # define YY_DECL \
int tlyylex (tlyy::parser::semantic_type *yylval, \ int tlyylex (tlyy::parser::semantic_type *yylval, \
spot::location *yylloc, \ spot::location *yylloc, \
spot::parse_error_list& error_list) spot::parse_error_list& error_list)
YY_DECL; YY_DECL;
void flex_set_buffer(const std::string& buf, int start_tok, bool lenient); void flex_set_buffer(const std::string& buf, int start_tok, bool lenient);

View file

@ -53,7 +53,7 @@ namespace spot
{ {
auto i = map_.find(name); auto i = map_.find(name);
if (i != map_.end()) if (i != map_.end())
return true; return true;
auto v = aut_->acc().add_set(); auto v = aut_->acc().add_set();
map_[name] = v; map_[name] = v;
return true; return true;
@ -63,7 +63,7 @@ namespace spot
{ {
auto p = map_.find(name); auto p = map_.find(name);
if (p == map_.end()) 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})); return std::make_pair(true, acc_cond::mark_t({p->second}));
} }
}; };
@ -83,9 +83,9 @@ namespace spot
std::pair<bool, acc_cond::mark_t> lookup(unsigned n) std::pair<bool, acc_cond::mark_t> lookup(unsigned n)
{ {
if (n < aut_->acc().num_sets()) 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 else
return std::make_pair(false, 0U); return std::make_pair(false, 0U);
} }
}; };
@ -106,13 +106,13 @@ namespace spot
{ {
auto p = map_.find(n); auto p = map_.find(n);
if (p != map_.end()) if (p != map_.end())
return std::make_pair(true, p->second); return std::make_pair(true, p->second);
if (used_ < aut_->acc().num_sets()) if (used_ < aut_->acc().num_sets())
{ {
auto res = acc_cond::mark_t({used_++}); auto res = acc_cond::mark_t({used_++});
map_[n] = res; map_[n] = res;
return std::make_pair(true, res); return std::make_pair(true, res);
} }
return std::make_pair(false, 0U); return std::make_pair(false, 0U);
} }
}; };

View file

@ -67,15 +67,15 @@ namespace spot
// externally), use the new variables. // externally), use the new variables.
if (lvarnum < varnum) if (lvarnum < varnum)
{ {
more -= varnum - lvarnum; more -= varnum - lvarnum;
lvarnum = varnum; lvarnum = varnum;
} }
// If we still need more variable, do allocate them. // If we still need more variable, do allocate them.
if (more > 0) if (more > 0)
{ {
bdd_extvarnum(more); bdd_extvarnum(more);
varnum += more; varnum += more;
lvarnum = varnum; lvarnum = varnum;
} }
} }
@ -98,19 +98,19 @@ namespace spot
// of the variable space, allocate just the difference. // of the variable space, allocate just the difference.
if (!fl.empty() && fl.back().first + fl.back().second == lvarnum) if (!fl.empty() && fl.back().first + fl.back().second == lvarnum)
{ {
int res = fl.back().first; int res = fl.back().first;
int endvar = fl.back().second; int endvar = fl.back().second;
assert(n > endvar); assert(n > endvar);
extvarnum(n - endvar); extvarnum(n - endvar);
fl.pop_back(); fl.pop_back();
return res; return res;
} }
else else
{ {
// Otherwise, allocate as much variables as we need. // Otherwise, allocate as much variables as we need.
int res = lvarnum; int res = lvarnum;
extvarnum(n); extvarnum(n);
return res; return res;
} }
} }
} }

View file

@ -41,24 +41,24 @@ namespace spot
free_list_type::iterator cur; free_list_type::iterator cur;
for (cur = fl.begin(); cur != fl.end(); ++cur) for (cur = fl.begin(); cur != fl.end(); ++cur)
{ {
if (cur->second < n) if (cur->second < n)
continue; continue;
if (n == cur->second) if (n == cur->second)
{ {
best = cur; best = cur;
break; break;
} }
if (best == fl.end() if (best == fl.end()
|| cur->second < best->second) || cur->second < best->second)
best = cur; best = cur;
} }
// We have found enough free variables. // We have found enough free variables.
if (best != fl.end()) if (best != fl.end())
{ {
int result = best->first; int result = best->first;
remove(best, result, n); remove(best, result, n);
return result; return result;
} }
// We haven't found enough adjacent free variables; // We haven't found enough adjacent free variables;
@ -73,67 +73,67 @@ namespace spot
int end = base + n; int end = base + n;
for (cur = fl.begin(); cur != fl.end(); ++cur) for (cur = fl.begin(); cur != fl.end(); ++cur)
{ {
int cend = cur->first + cur->second; int cend = cur->first + cur->second;
// cur [...] // cur [...]
// to insert [...] // to insert [...]
// ----------------------- // -----------------------
// result [...] [...] // result [...] [...]
// (Insert a new range, unconnected.) // (Insert a new range, unconnected.)
if (cur->first > end) if (cur->first > end)
{ {
break; break;
} }
// cur [...] // cur [...]
// to insert [...] // to insert [...]
// ----------------------- // -----------------------
// result unknown : we should look at the rest of the freelist. // result unknown : we should look at the rest of the freelist.
else if (base > cend) else if (base > cend)
{ {
continue; continue;
} }
// cur [....[ [......[ // cur [....[ [......[
// to insert [....[ [..[ // to insert [....[ [..[
// ---------------------------------- // ----------------------------------
// result [......[ [......[ // result [......[ [......[
else if (cur->first <= base) else if (cur->first <= base)
{ {
if (cend >= end) if (cend >= end)
// second case : nothing to do // second case : nothing to do
return; return;
// cur->second is set below. // cur->second is set below.
} }
// cur [....[ [..[ // cur [....[ [..[
// to insert [....[ [.......[ // to insert [....[ [.......[
// ---------------------------------- // ----------------------------------
// result [......[ [.......[ // result [......[ [.......[
else else
{ {
cur->first = base; cur->first = base;
// cur->second is set below. // cur->second is set below.
} }
// We get here in one of these three situations: // We get here in one of these three situations:
// //
// cur [....[ [....[ [..[ // cur [....[ [....[ [..[
// to insert [....[ [....[ [.......[ // to insert [....[ [....[ [.......[
// ------------------------------------------- // -------------------------------------------
// result [......[ [......[ [.......[ // result [......[ [......[ [.......[
// //
// cur->first is already set, be cur->second has yet to be. // cur->first is already set, be cur->second has yet to be.
end = std::max(cend, end); end = std::max(cend, end);
cur->second = end - cur->first; cur->second = end - cur->first;
// Since we have extended the current range, maybe the next // Since we have extended the current range, maybe the next
// items on the list should be merged. // items on the list should be merged.
free_list_type::iterator next = cur; free_list_type::iterator next = cur;
++next; ++next;
while (next != fl.end() && next->first <= end) while (next != fl.end() && next->first <= end)
{ {
end = std::max(next->first + next->second, end); end = std::max(next->first + next->second, end);
cur->second = end - cur->first; cur->second = end - cur->first;
free_list_type::iterator next2 = next++; free_list_type::iterator next2 = next++;
fl.erase(next2); fl.erase(next2);
} }
return; return;
} }
// We reach this place either because a new unconnected range // We reach this place either because a new unconnected range
@ -148,15 +148,15 @@ namespace spot
int end = base + n; int end = base + n;
while (cur != fl.end() && cur->first < end) while (cur != fl.end() && cur->first < end)
{ {
int cend = cur->first + cur->second; int cend = cur->first + cur->second;
// Remove may invalidate the current iterator, so advance it first. // Remove may invalidate the current iterator, so advance it first.
free_list_type::iterator old = cur++; free_list_type::iterator old = cur++;
if (cend >= base) if (cend >= base)
{ {
int newbase = std::max(base, old->first); int newbase = std::max(base, old->first);
int q = std::min(cend, end) - newbase; int q = std::min(cend, end) - newbase;
remove(old, newbase, q); remove(old, newbase, q);
} }
} }
} }
@ -165,31 +165,31 @@ namespace spot
{ {
if (base == i->first) if (base == i->first)
{ {
// Removing at the beginning of the range // Removing at the beginning of the range
i->second -= n; i->second -= n;
assert(i->second >= 0); assert(i->second >= 0);
// Erase the range if it's now empty. // Erase the range if it's now empty.
if (i->second == 0) if (i->second == 0)
fl.erase(i); fl.erase(i);
else else
i->first += n; i->first += n;
} }
else if (base + n == i->first + i->second) else if (base + n == i->first + i->second)
{ {
// Removing at the end of the range // Removing at the end of the range
i->second -= n; i->second -= n;
assert(i->second > 0); // cannot be empty because base != i->first assert(i->second > 0); // cannot be empty because base != i->first
} }
else else
{ {
// Removing in the middle of a range. // Removing in the middle of a range.
int b1 = i->first; int b1 = i->first;
int n1 = base - i->first; int n1 = base - i->first;
int n2 = i->first + i->second - base - n; int n2 = i->first + i->second - base - n;
assert(n1 > 0); assert(n1 > 0);
assert(n2 > 0); assert(n2 > 0);
*i = pos_lenght_pair(base + n, n2); *i = pos_lenght_pair(base + n, n2);
fl.insert(i, pos_lenght_pair(b1, n1)); fl.insert(i, pos_lenght_pair(b1, n1));
} }
} }

View file

@ -29,11 +29,11 @@ namespace spot
trim(std::string& str) trim(std::string& str)
{ {
str.erase(std::find_if(str.rbegin(), str.rend(), str.erase(std::find_if(str.rbegin(), str.rend(),
std::not1(std::ptr_fun<int, int> std::not1(std::ptr_fun<int, int>
(std::isspace))).base(), (std::isspace))).base(),
str.end()); str.end());
str.erase(str.begin(), str.erase(str.begin(),
std::find_if(str.begin(), str.end(), std::find_if(str.begin(), str.end(),
std::not1(std::ptr_fun<int, int>(std::isspace)))); std::not1(std::ptr_fun<int, int>(std::isspace))));
} }
} }

View file

@ -42,7 +42,7 @@ namespace spot
{ {
for (auto s: a.sets()) for (auto s: a.sets())
if (m[s] > 0) if (m[s] > 0)
--m[s]; --m[s];
return *this; return *this;
} }
@ -52,7 +52,7 @@ namespace spot
std::vector<unsigned> res; std::vector<unsigned> res;
for (unsigned n = 0; n < max; ++n) for (unsigned n = 0; n < max; ++n)
if (m[n] > w.m[n]) if (m[n] > w.m[n])
res.push_back(n); res.push_back(n);
return acc_cond::mark_t(res.begin(), res.end()); return acc_cond::mark_t(res.begin(), res.end());
} }

View file

@ -48,7 +48,7 @@ namespace spot
/// the corresponding counter in w. /// the corresponding counter in w.
acc_cond::mark_t diff(const acc_cond& acc, const weight& w) const; acc_cond::mark_t diff(const acc_cond& acc, const weight& w) const;
friend std::ostream& operator<<(std::ostream& os, friend std::ostream& operator<<(std::ostream& os,
const weight& w); const weight& w);
private: private:
std::vector<int> m; std::vector<int> m;

View file

@ -276,7 +276,7 @@ namespace spot
bool is_stuttering_transition = (get_tgba_condition() bool is_stuttering_transition = (get_tgba_condition()
== (dest)->get_tgba_condition()); == (dest)->get_tgba_condition());
bool dest_is_livelock_accepting = bool dest_is_livelock_accepting =
dest->is_livelock_accepting_state(); dest->is_livelock_accepting_state();
//Before deleting stuttering transitions, propaged back livelock //Before deleting stuttering transitions, propaged back livelock
//and initial state's properties //and initial state's properties
@ -319,7 +319,7 @@ namespace spot
// they are not cloned. // they are not cloned.
if (trans) if (trans)
for (auto& t: *trans) for (auto& t: *trans)
delete t; delete t;
delete trans; delete trans;
std::unordered_map<int, transitions*, std::hash<int> >::iterator i = std::unordered_map<int, transitions*, std::hash<int> >::iterator i =
@ -338,8 +338,8 @@ namespace spot
ta_explicit::ta_explicit(const const_twa_ptr& tgba, ta_explicit::ta_explicit(const const_twa_ptr& tgba,
unsigned n_acc, unsigned n_acc,
state_ta_explicit* artificial_initial_state): state_ta_explicit* artificial_initial_state):
ta(tgba->get_dict()), ta(tgba->get_dict()),
tgba_(tgba), tgba_(tgba),
artificial_initial_state_(artificial_initial_state) artificial_initial_state_(artificial_initial_state)
@ -351,7 +351,7 @@ namespace spot
{ {
auto is = add_state(artificial_initial_state); auto is = add_state(artificial_initial_state);
assert(is == 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) for (it = states_set_.begin(); it != states_set_.end(); ++it)
{ {
auto* s = const_cast<state_ta_explicit*> auto* s = const_cast<state_ta_explicit*>
(down_cast<const state_ta_explicit*>(*it)); (down_cast<const state_ta_explicit*>(*it));
assert(s); assert(s);
s->free_transitions(); s->free_transitions();
s->get_tgba_state()->destroy(); s->get_tgba_state()->destroy();
delete s; delete s;
@ -390,11 +390,11 @@ namespace spot
auto add_state = initial_states_set_.insert(s); auto add_state = initial_states_set_.insert(s);
if (get_artificial_initial_state()) if (get_artificial_initial_state())
if (add_state.second) if (add_state.second)
{ {
auto i = auto i =
down_cast<state_ta_explicit*>(get_artificial_initial_state()); down_cast<state_ta_explicit*>(get_artificial_initial_state());
create_transition(i, condition, 0U, s); create_transition(i, condition, 0U, s);
} }
} }
void void
@ -411,9 +411,9 @@ namespace spot
void void
ta_explicit::create_transition(state_ta_explicit* source, bdd condition, ta_explicit::create_transition(state_ta_explicit* source, bdd condition,
acc_cond::mark_t acceptance_conditions, acc_cond::mark_t acceptance_conditions,
const state_ta_explicit* dest, const state_ta_explicit* dest,
bool add_at_beginning) bool add_at_beginning)
{ {
state_ta_explicit::transition* t = new state_ta_explicit::transition; state_ta_explicit::transition* t = new state_ta_explicit::transition;
t->dest = dest; t->dest = dest;

View file

@ -41,8 +41,8 @@ namespace spot
{ {
public: public:
ta_explicit(const const_twa_ptr& tgba, ta_explicit(const const_twa_ptr& tgba,
unsigned n_acc, unsigned n_acc,
state_ta_explicit* artificial_initial_state = nullptr); state_ta_explicit* artificial_initial_state = nullptr);
const_twa_ptr const_twa_ptr
get_tgba() const; get_tgba() const;
@ -55,9 +55,9 @@ namespace spot
void void
create_transition(state_ta_explicit* source, bdd condition, create_transition(state_ta_explicit* source, bdd condition,
acc_cond::mark_t acceptance_conditions, acc_cond::mark_t acceptance_conditions,
const state_ta_explicit* dest, const state_ta_explicit* dest,
bool add_at_beginning = false); bool add_at_beginning = false);
void void
delete_stuttering_transitions(); delete_stuttering_transitions();
@ -142,10 +142,10 @@ namespace spot
typedef std::list<transition*> transitions; typedef std::list<transition*> transitions;
state_ta_explicit(const state* tgba_state, const bdd tgba_condition, state_ta_explicit(const state* tgba_state, const bdd tgba_condition,
bool is_initial_state = false, bool is_initial_state = false,
bool is_accepting_state = false, bool is_accepting_state = false,
bool is_livelock_accepting_state = false, bool is_livelock_accepting_state = false,
transitions* trans = nullptr) : transitions* trans = nullptr) :
tgba_state_(tgba_state), tgba_condition_(tgba_condition), tgba_state_(tgba_state), tgba_condition_(tgba_condition),
is_initial_state_(is_initial_state), is_accepting_state_( is_initial_state_(is_initial_state), is_accepting_state_(
is_accepting_state), is_livelock_accepting_state_( is_accepting_state), is_livelock_accepting_state_(
@ -246,8 +246,8 @@ namespace spot
inline ta_explicit_ptr inline ta_explicit_ptr
make_ta_explicit(const const_twa_ptr& tgba, make_ta_explicit(const const_twa_ptr& tgba,
unsigned n_acc, unsigned n_acc,
state_ta_explicit* artificial_initial_state = nullptr) state_ta_explicit* artificial_initial_state = nullptr)
{ {
return std::make_shared<ta_explicit>(tgba, n_acc, artificial_initial_state); return std::make_shared<ta_explicit>(tgba, n_acc, artificial_initial_state);
} }

View file

@ -67,8 +67,8 @@ namespace spot
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// ta_succ_iterator_product // ta_succ_iterator_product
ta_succ_iterator_product::ta_succ_iterator_product(const state_ta_product* s, ta_succ_iterator_product::ta_succ_iterator_product(const state_ta_product* s,
const ta* t, const ta* t,
const kripke* k) const kripke* k)
: source_(s), ta_(t), kripke_(k) : source_(s), ta_(t), kripke_(k)
{ {
kripke_source_condition = kripke_->state_condition(s->get_kripke_state()); 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, 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()), ta(testing_automata->get_dict()),
dict_(testing_automata->get_dict()), dict_(testing_automata->get_dict()),
ta_(testing_automata), ta_(testing_automata),
@ -292,9 +292,9 @@ namespace spot
for (auto s: ta_init_states_set) for (auto s: ta_init_states_set)
if (artificial_initial_state || if (artificial_initial_state ||
(kripke_init_condition == ta_->get_state_condition(s))) (kripke_init_condition == ta_->get_state_condition(s)))
initial_states_set.insert(new state_ta_product(s, initial_states_set.insert(new state_ta_product(s,
kripke_init->clone())); kripke_init->clone()));
kripke_init->destroy(); kripke_init->destroy();
return initial_states_set; return initial_states_set;
@ -316,8 +316,8 @@ namespace spot
const state_ta_product* stp = down_cast<const state_ta_product*> (s); const state_ta_product* stp = down_cast<const state_ta_product*> (s);
assert(s); assert(s);
return new ta_succ_iterator_product_by_changeset(stp, return new ta_succ_iterator_product_by_changeset(stp,
ta_.get(), kripke_.get(), ta_.get(), kripke_.get(),
changeset); changeset);
} }
@ -402,7 +402,7 @@ namespace spot
ta_succ_iterator_product_by_changeset:: ta_succ_iterator_product_by_changeset::
ta_succ_iterator_product_by_changeset(const state_ta_product* s, const ta* t, 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) : ta_succ_iterator_product(s, t, k)
{ {
current_condition_ = changeset; current_condition_ = changeset;

View file

@ -131,7 +131,7 @@ namespace spot
/// \param testing_automaton The TA component in the product. /// \param testing_automaton The TA component in the product.
/// \param kripke_structure The Kripke component in the product. /// \param kripke_structure The Kripke component in the product.
ta_product(const const_ta_ptr& testing_automaton, ta_product(const const_ta_ptr& testing_automaton,
const const_kripke_ptr& kripke_structure); const const_kripke_ptr& kripke_structure);
virtual virtual
~ta_product(); ~ta_product();
@ -197,7 +197,7 @@ namespace spot
typedef std::shared_ptr<ta_product> ta_product_ptr; typedef std::shared_ptr<ta_product> ta_product_ptr;
typedef std::shared_ptr<const ta_product> const_ta_product_ptr; typedef std::shared_ptr<const ta_product> const_ta_product_ptr;
inline ta_product_ptr product(const const_ta_ptr& testing_automaton, 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<ta_product>(testing_automaton, kripke_structure); return std::make_shared<ta_product>(testing_automaton, kripke_structure);
} }
@ -207,8 +207,8 @@ namespace spot
{ {
public: public:
ta_succ_iterator_product_by_changeset(const state_ta_product* s, ta_succ_iterator_product_by_changeset(const state_ta_product* s,
const ta* t, const kripke* k, const ta* t, const kripke* k,
bdd changeset); bdd changeset);
/// \brief Move to the next successor in the Kripke structure /// \brief Move to the next successor in the Kripke structure
void next_kripke_dest(); void next_kripke_dest();

View file

@ -25,8 +25,8 @@ namespace spot
{ {
tgta_explicit::tgta_explicit(const const_twa_ptr& tgba, tgta_explicit::tgta_explicit(const const_twa_ptr& tgba,
unsigned n_acc, unsigned n_acc,
state_ta_explicit* artificial_initial_state) : state_ta_explicit* artificial_initial_state) :
tgta(tgba->get_dict()), tgta(tgba->get_dict()),
ta_(make_ta_explicit(tgba, n_acc, artificial_initial_state)) ta_(make_ta_explicit(tgba, n_acc, artificial_initial_state))
{ {

View file

@ -38,8 +38,8 @@ namespace spot
{ {
public: public:
tgta_explicit(const const_twa_ptr& tgba, tgta_explicit(const const_twa_ptr& tgba,
unsigned n_acc, unsigned n_acc,
state_ta_explicit* artificial_initial_state); state_ta_explicit* artificial_initial_state);
// tgba interface // tgba interface
virtual spot::state* get_init_state() const override; virtual spot::state* get_init_state() const override;
@ -63,9 +63,9 @@ namespace spot
inline tgta_explicit_ptr inline tgta_explicit_ptr
make_tgta_explicit(const const_twa_ptr& tgba, unsigned n_acc, 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<tgta_explicit>(tgba, n_acc, return std::make_shared<tgta_explicit>(tgba, n_acc,
artificial_initial_state); artificial_initial_state);
} }
} }

View file

@ -44,7 +44,7 @@ namespace spot
// tgta_product // tgta_product
tgta_product::tgta_product(const const_kripke_ptr& left, tgta_product::tgta_product(const const_kripke_ptr& left,
const const_tgta_ptr& right): const const_tgta_ptr& right):
twa_product(left, right) twa_product(left, right)
{ {
} }
@ -207,7 +207,7 @@ namespace spot
kripke_current_dest_state->clone(), kripke_current_dest_state->clone(),
tgta_succ_it_->dst(), pool_); tgta_succ_it_->dst(), pool_);
current_acceptance_conditions_ current_acceptance_conditions_
= tgta_succ_it_->acc(); = tgta_succ_it_->acc();
return true; return true;
} }

View file

@ -33,7 +33,7 @@ namespace spot
{ {
public: public:
tgta_product(const const_kripke_ptr& left, 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; virtual const state* get_init_state() const override;
@ -42,7 +42,7 @@ namespace spot
}; };
inline twa_ptr product(const const_kripke_ptr& left, inline twa_ptr product(const const_kripke_ptr& left,
const const_tgta_ptr& right) const const_tgta_ptr& right)
{ {
return std::make_shared<tgta_product>(left, right); return std::make_shared<tgta_product>(left, right);
} }
@ -52,9 +52,9 @@ namespace spot
{ {
public: public:
tgta_succ_iterator_product(const state_product* s, tgta_succ_iterator_product(const state_product* s,
const const_kripke_ptr& k, const const_kripke_ptr& k,
const const_tgta_ptr& tgta, const const_tgta_ptr& tgta,
fixed_size_pool* pool); fixed_size_pool* pool);
virtual virtual
~tgta_succ_iterator_product(); ~tgta_succ_iterator_product();

View file

@ -35,109 +35,109 @@ namespace spot
void void
parse_opts(const char* options) parse_opts(const char* options)
{ {
const char* orig = options; const char* orig = options;
while (char c = *options++) while (char c = *options++)
switch (c) switch (c)
{ {
case '.': case '.':
{ {
// Copy the value in a string, so future calls to // Copy the value in a string, so future calls to
// parse_opts do not fail if the environment has // parse_opts do not fail if the environment has
// changed. (This matters particularly in an ipython // changed. (This matters particularly in an ipython
// notebook, where it is tempting to redefine // notebook, where it is tempting to redefine
// SPOT_DOTDEFAULT.) // SPOT_DOTDEFAULT.)
static std::string def = []() static std::string def = []()
{ {
auto s = getenv("SPOT_DOTDEFAULT"); auto s = getenv("SPOT_DOTDEFAULT");
return s ? s : ""; return s ? s : "";
}(); }();
// Prevent infinite recursions... // Prevent infinite recursions...
if (orig == def.c_str()) if (orig == def.c_str())
throw std::runtime_error throw std::runtime_error
(std::string("SPOT_DOTDEFAULT should not contain '.'")); (std::string("SPOT_DOTDEFAULT should not contain '.'"));
if (!def.empty()) if (!def.empty())
parse_opts(def.c_str()); parse_opts(def.c_str());
break; break;
} }
case 'A': case 'A':
opt_hide_sets_ = true; opt_hide_sets_ = true;
break; break;
case 'c': case 'c':
opt_circles_ = true; opt_circles_ = true;
break; break;
case 'C': case 'C':
if (*options != '(') if (*options != '(')
throw std::runtime_error throw std::runtime_error
("invalid node color specification for print_dot()"); ("invalid node color specification for print_dot()");
{ {
auto* end = strchr(++options, ')'); auto* end = strchr(++options, ')');
if (!end) if (!end)
throw std::runtime_error throw std::runtime_error
("invalid node color specification for print_dot()"); ("invalid node color specification for print_dot()");
opt_node_color_ = std::string(options, end - options); opt_node_color_ = std::string(options, end - options);
options = end + 1; options = end + 1;
} }
break; break;
case 'h': case 'h':
opt_horizontal_ = true; opt_horizontal_ = true;
break; break;
case 'f': case 'f':
if (*options != '(') if (*options != '(')
throw std::runtime_error throw std::runtime_error
(std::string("invalid font specification for dotty()")); (std::string("invalid font specification for dotty()"));
{ {
auto* end = strchr(++options, ')'); auto* end = strchr(++options, ')');
if (!end) if (!end)
throw std::runtime_error throw std::runtime_error
(std::string("invalid font specification for dotty()")); (std::string("invalid font specification for dotty()"));
opt_font_ = std::string(options, end - options); opt_font_ = std::string(options, end - options);
options = end + 1; options = end + 1;
} }
break; break;
case 'v': case 'v':
opt_horizontal_ = false; opt_horizontal_ = false;
break; break;
case '0': case '0':
case '1': case '1':
case '2': case '2':
case '3': case '3':
case '4': case '4':
case '5': case '5':
case '6': case '6':
case '7': case '7':
case '8': case '8':
case '9': case '9':
case 'a': case 'a':
case 'b': case 'b':
case 'B': case 'B':
case 'e': case 'e':
case 'n': case 'n':
case 'N': case 'N':
case 'o': case 'o':
case 'r': case 'r':
case 'R': case 'R':
case 's': case 's':
case 't': case 't':
case '+': case '+':
case '<': case '<':
case '#': case '#':
// All these options are implemented by dotty() on TGBA, // All these options are implemented by dotty() on TGBA,
// but are not implemented here. We simply ignore them, // but are not implemented here. We simply ignore them,
// because raising an exception if they are in // because raising an exception if they are in
// SPOT_DEFAULT would be annoying. // SPOT_DEFAULT would be annoying.
break; break;
default: default:
throw std::runtime_error throw std::runtime_error
(std::string("unknown option for dotty(): ") + c); (std::string("unknown option for dotty(): ") + c);
} }
} }
public: public:
dotty_bfs(std::ostream& os, const const_ta_ptr& a, dotty_bfs(std::ostream& os, const const_ta_ptr& a,
const char* opt) : const char* opt) :
ta_reachable_iterator_breadth_first(a), os_(os) ta_reachable_iterator_breadth_first(a), os_(os)
{ {
parse_opts(opt ? opt : "."); parse_opts(opt ? opt : ".");
} }
void void
@ -145,56 +145,56 @@ namespace spot
{ {
os_ << "digraph G {\n"; os_ << "digraph G {\n";
if (opt_horizontal_) if (opt_horizontal_)
os_ << " rankdir=LR\n"; os_ << " rankdir=LR\n";
if (opt_circles_) if (opt_circles_)
os_ << " node [shape=\"circle\"]\n"; os_ << " node [shape=\"circle\"]\n";
if (!opt_node_color_.empty()) if (!opt_node_color_.empty())
os_ << " node [style=\"filled\", fillcolor=\"" os_ << " node [style=\"filled\", fillcolor=\""
<< opt_node_color_ << "\"]\n"; << opt_node_color_ << "\"]\n";
if (!opt_font_.empty()) if (!opt_font_.empty())
os_ << " fontname=\"" << opt_font_ os_ << " fontname=\"" << opt_font_
<< "\"\n node [fontname=\"" << opt_font_ << "\"\n node [fontname=\"" << opt_font_
<< "\"]\n edge [fontname=\"" << opt_font_ << "\"]\n edge [fontname=\"" << opt_font_
<< "\"]\n"; << "\"]\n";
// Always copy the environment variable into a static string, // Always copy the environment variable into a static string,
// so that we (1) look it up once, but (2) won't crash if the // so that we (1) look it up once, but (2) won't crash if the
// environment is changed. // environment is changed.
static std::string extra = []() static std::string extra = []()
{ {
auto s = getenv("SPOT_DOTEXTRA"); auto s = getenv("SPOT_DOTEXTRA");
return s ? s : ""; return s ? s : "";
}(); }();
// Any extra text passed in the SPOT_DOTEXTRA environment // Any extra text passed in the SPOT_DOTEXTRA environment
// variable should be output at the end of the "header", so // variable should be output at the end of the "header", so
// that our setup can be overridden. // that our setup can be overridden.
if (!extra.empty()) if (!extra.empty())
os_ << " " << extra << '\n'; os_ << " " << extra << '\n';
artificial_initial_state_ = t_automata_->get_artificial_initial_state(); artificial_initial_state_ = t_automata_->get_artificial_initial_state();
ta::const_states_set_t init_states_set; ta::const_states_set_t init_states_set;
if (artificial_initial_state_) if (artificial_initial_state_)
{ {
init_states_set.insert(artificial_initial_state_); init_states_set.insert(artificial_initial_state_);
os_ << " 0 [label=\"\", style=invis, height=0]\n 0 -> 1\n"; os_ << " 0 [label=\"\", style=invis, height=0]\n 0 -> 1\n";
} }
else else
{ {
int n = 0; int n = 0;
init_states_set = t_automata_->get_initial_states_set(); init_states_set = t_automata_->get_initial_states_set();
for (auto s: init_states_set) for (auto s: init_states_set)
{ {
bdd init_condition = t_automata_->get_state_condition(s); bdd init_condition = t_automata_->get_state_condition(s);
std::string label = bdd_format_formula(t_automata_->get_dict(), std::string label = bdd_format_formula(t_automata_->get_dict(),
init_condition); init_condition);
++n; ++n;
os_ << " " << -n << " [label=\"\", style=invis, height=0]\n " os_ << " " << -n << " [label=\"\", style=invis, height=0]\n "
<< -n << " -> " << n << " [label=\"" << label << "\"]\n"; << -n << " -> " << n << " [label=\"" << label << "\"]\n";
} }
} }
} }
void void
@ -209,41 +209,41 @@ namespace spot
std::string style; std::string style;
if (t_automata_->is_accepting_state(s)) if (t_automata_->is_accepting_state(s))
style = ",peripheries=2"; style = ",peripheries=2";
if (t_automata_->is_livelock_accepting_state(s)) if (t_automata_->is_livelock_accepting_state(s))
style += ",shape=box"; style += ",shape=box";
os_ << " " << n << " [label="; os_ << " " << n << " [label=";
if (s == artificial_initial_state_) if (s == artificial_initial_state_)
os_ << "init"; os_ << "init";
else else
os_ << quote_unless_bare_word(t_automata_->format_state(s)); os_ << quote_unless_bare_word(t_automata_->format_state(s));
os_ << style << "]\n"; os_ << style << "]\n";
} }
void void
process_link(int in, int out, const ta_succ_iterator* si) process_link(int in, int out, const ta_succ_iterator* si)
{ {
bdd_dict_ptr d = t_automata_->get_dict(); bdd_dict_ptr d = t_automata_->get_dict();
std::string label = std::string label =
((in == 1 && artificial_initial_state_) ((in == 1 && artificial_initial_state_)
? bdd_format_formula(d, si->cond()) ? bdd_format_formula(d, si->cond())
: bdd_format_accset(d, si->cond())); : bdd_format_accset(d, si->cond()));
if (label.empty()) if (label.empty())
label = "{}"; label = "{}";
if (!opt_hide_sets_) if (!opt_hide_sets_)
{ {
label += "\n"; label += "\n";
label += t_automata_->acc(). label += t_automata_->acc().
format(si->acc()); format(si->acc());
} }
os_ << " " << in << " -> " << out << " [label=\""; os_ << " " << in << " -> " << out << " [label=\"";
escape_str(os_, label); escape_str(os_, label);
os_ << "\"]\n"; os_ << "\"]\n";
} }
private: private:

View file

@ -26,5 +26,5 @@ namespace spot
{ {
SPOT_API std::ostream& SPOT_API std::ostream&
print_dot(std::ostream& os, const const_ta_ptr& a, print_dot(std::ostream& os, const const_ta_ptr& a,
const char* opt = nullptr); const char* opt = nullptr);
} }

View file

@ -102,10 +102,10 @@ namespace spot
(ta_init_it_->dst()), kripke_init_state->clone()); (ta_init_it_->dst()), kripke_init_state->clone());
if (!h.emplace(init, num + 1).second) if (!h.emplace(init, num + 1).second)
{ {
init->destroy(); init->destroy();
continue; continue;
} }
scc.push(++num); scc.push(++num);
arc.push(0U); arc.push(0U);
@ -146,7 +146,7 @@ namespace spot
} }
// fill rem with any component removed, // fill rem with any component removed,
auto i = h.find(curr); auto i = h.find(curr);
assert(i != h.end()); assert(i != h.end());
scc.rem().push_front(curr); scc.rem().push_front(curr);
@ -168,7 +168,7 @@ namespace spot
{ {
// removing states // removing states
for (auto j: scc.rem()) for (auto j: scc.rem())
h[j] = -1; h[j] = -1;
dec_depth(scc.rem().size()); dec_depth(scc.rem().size());
scc.pop(); scc.pop();
assert(!arc.empty()); assert(!arc.empty());
@ -209,7 +209,7 @@ namespace spot
// We do not need SUCC from now on. // We do not need SUCC from now on.
// Are we going to a new state? // Are we going to a new state?
auto p = h.emplace(dest, num + 1); auto p = h.emplace(dest, num + 1);
if (p.second) if (p.second)
{ {
// Number it, stack it, and register its successors // Number it, stack it, and register its successors
@ -277,23 +277,23 @@ namespace spot
scc.rem().splice(scc.rem().end(), rem); scc.rem().splice(scc.rem().end(), rem);
bool is_accepting_sscc = scc.top().is_accepting bool is_accepting_sscc = scc.top().is_accepting
|| a_->acc().accepting(scc.top().condition); || a_->acc().accepting(scc.top().condition);
if (is_accepting_sscc) if (is_accepting_sscc)
{ {
trace trace
<< "PASS 1: SUCCESS: a_->is_livelock_accepting_state(curr): " << "PASS 1: SUCCESS: a_->is_livelock_accepting_state(curr): "
<< a_->is_livelock_accepting_state(curr) << '\n'; << a_->is_livelock_accepting_state(curr) << '\n';
trace trace
<< "PASS 1: scc.top().condition : " << "PASS 1: scc.top().condition : "
<< scc.top().condition << '\n'; << scc.top().condition << '\n';
trace trace
<< "PASS 1: a_->acc().all_sets() : " << "PASS 1: a_->acc().all_sets() : "
<< (a_->acc().all_sets()) << '\n'; << (a_->acc().all_sets()) << '\n';
trace trace
<< ("PASS 1 CYCLE and accepting? ") << ("PASS 1 CYCLE and accepting? ")
<< a_->acc().accepting(scc.top().condition) << a_->acc().accepting(scc.top().condition)
<< std::endl; << std::endl;
clear(h, todo, ta_init_it_); clear(h, todo, ta_init_it_);
return true; return true;
} }
@ -315,19 +315,19 @@ namespace spot
h_livelock_root = h[livelock_roots.top()]; h_livelock_root = h[livelock_roots.top()];
if (heuristic_livelock_detection(dest, h, h_livelock_root, if (heuristic_livelock_detection(dest, h, h_livelock_root,
liveset_curr)) liveset_curr))
{ {
clear(h, todo, ta_init_it_); clear(h, todo, ta_init_it_);
return true; return true;
} }
for (const state* succ: liveset_dest) for (const state* succ: liveset_dest)
if (heuristic_livelock_detection(succ, h, h_livelock_root, if (heuristic_livelock_detection(succ, h, h_livelock_root,
liveset_curr)) liveset_curr))
{ {
clear(h, todo, ta_init_it_); clear(h, todo, ta_init_it_);
return true; return true;
} }
} }
} }
@ -403,11 +403,11 @@ namespace spot
auto init = ta_init_it_.front(); auto init = ta_init_it_.front();
ta_init_it_.pop(); ta_init_it_.pop();
if (!h.emplace(init, num + 1).second) if (!h.emplace(init, num + 1).second)
{ {
init->destroy(); init->destroy();
continue; continue;
} }
sscc.push(num); sscc.push(num);
sscc.top().is_accepting = t->is_livelock_accepting_state(init); sscc.top().is_accepting = t->is_livelock_accepting_state(init);
@ -435,7 +435,7 @@ namespace spot
trace << "PASS 2 : backtrack\n"; trace << "PASS 2 : backtrack\n";
// fill rem with any component removed, // fill rem with any component removed,
auto i = h.find(curr); auto i = h.find(curr);
assert(i != h.end()); assert(i != h.end());
sscc.rem().push_front(curr); sscc.rem().push_front(curr);
@ -449,7 +449,7 @@ namespace spot
{ {
// removing states // removing states
for (auto j: sscc.rem()) for (auto j: sscc.rem())
h[j] = -1; h[j] = -1;
dec_depth(sscc.rem().size()); dec_depth(sscc.rem().size());
sscc.pop(); sscc.pop();
} }
@ -498,10 +498,10 @@ namespace spot
inc_depth(); inc_depth();
continue; continue;
} }
else else
{ {
dest->destroy(); dest->destroy();
} }
// If we have reached a dead component, ignore it. // If we have reached a dead component, ignore it.
if (i->second == -1) if (i->second == -1)
@ -509,12 +509,12 @@ namespace spot
//self loop state //self loop state
if (!curr->compare(i->first)) if (!curr->compare(i->first))
if (t->is_livelock_accepting_state(curr)) if (t->is_livelock_accepting_state(curr))
{ {
clear(h, todo, ta_init_it_); clear(h, todo, ta_init_it_);
trace << "PASS 2: SUCCESS\n"; trace << "PASS 2: SUCCESS\n";
return true; return true;
} }
// Now this is the most interesting case. We have reached a // Now this is the most interesting case. We have reached a
// state S1 which is already part of a non-dead SSCC. Any such // state S1 which is already part of a non-dead SSCC. Any such

View file

@ -34,7 +34,7 @@ namespace spot
namespace namespace
{ {
typedef std::pair<const spot::state*, typedef std::pair<const spot::state*,
ta_succ_iterator_product*> pair_state_iter; ta_succ_iterator_product*> pair_state_iter;
} }
/// \addtogroup ta_emptiness_check Emptiness-checks /// \addtogroup ta_emptiness_check Emptiness-checks
@ -111,7 +111,7 @@ namespace spot
/// this heuristic is described in the paper cited above /// this heuristic is described in the paper cited above
bool bool
check(bool disable_second_pass = false, 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 /// \brief Check whether the product automaton contains
/// a livelock-accepting run /// a livelock-accepting run

View file

@ -47,8 +47,8 @@ namespace spot
{ {
static std::ostream& static std::ostream&
dump_hash_set(const hash_set* hs, dump_hash_set(const hash_set* hs,
const const_ta_ptr& aut, const const_ta_ptr& aut,
std::ostream& out) std::ostream& out)
{ {
out << '{'; out << '{';
const char* sep = ""; const char* sep = "";
@ -73,7 +73,7 @@ namespace spot
// automaton // automaton
static void static void
build_result(const const_ta_ptr& a, std::list<hash_set*>& sets, build_result(const const_ta_ptr& a, std::list<hash_set*>& 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 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 // For a state s, state_num[s] is the number of the state in the minimal
@ -82,103 +82,103 @@ namespace spot
std::list<hash_set*>::iterator sit; std::list<hash_set*>::iterator sit;
unsigned num = 0; unsigned num = 0;
for (sit = sets.begin(); sit != sets.end(); ++sit) for (sit = sets.begin(); sit != sets.end(); ++sit)
{ {
hash_set::iterator hit; hash_set::iterator hit;
hash_set* h = *sit; hash_set* h = *sit;
for (hit = h->begin(); hit != h->end(); ++hit) for (hit = h->begin(); hit != h->end(); ++hit)
state_num[*hit] = num; state_num[*hit] = num;
result_tgba->new_state(); result_tgba->new_state();
++num; ++num;
} }
// For each transition in the initial automaton, add the corresponding // For each transition in the initial automaton, add the corresponding
// transition in ta. // transition in ta.
for (sit = sets.begin(); sit != sets.end(); ++sit) for (sit = sets.begin(); sit != sets.end(); ++sit)
{ {
hash_set::iterator hit; hash_set::iterator hit;
hash_set* h = *sit; hash_set* h = *sit;
hit = h->begin(); hit = h->begin();
const state* src = *hit; const state* src = *hit;
unsigned src_num = state_num[src]; unsigned src_num = state_num[src];
bdd tgba_condition = bddtrue; bdd tgba_condition = bddtrue;
bool is_initial_state = a->is_initial_state(src); bool is_initial_state = a->is_initial_state(src);
if (!a->get_artificial_initial_state() && is_initial_state) if (!a->get_artificial_initial_state() && is_initial_state)
tgba_condition = a->get_state_condition(src); tgba_condition = a->get_state_condition(src);
bool is_accepting_state = a->is_accepting_state(src); bool is_accepting_state = a->is_accepting_state(src);
bool is_livelock_accepting_state = bool is_livelock_accepting_state =
a->is_livelock_accepting_state(src); a->is_livelock_accepting_state(src);
state_ta_explicit* new_src = state_ta_explicit* new_src =
new state_ta_explicit(result_tgba->state_from_number(src_num), new state_ta_explicit(result_tgba->state_from_number(src_num),
tgba_condition, is_initial_state, tgba_condition, is_initial_state,
is_accepting_state, is_accepting_state,
is_livelock_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) if (ta_src != new_src)
{ {
delete new_src; delete new_src;
} }
else if (a->get_artificial_initial_state()) else if (a->get_artificial_initial_state())
{ {
if (a->get_artificial_initial_state() == src) if (a->get_artificial_initial_state() == src)
result->set_artificial_initial_state(new_src); result->set_artificial_initial_state(new_src);
} }
else if (is_initial_state) else if (is_initial_state)
{ {
result->add_to_initial_states_set(new_src); 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()) for (succit->first(); !succit->done(); succit->next())
{ {
const state* dst = succit->dst(); const state* dst = succit->dst();
hash_map::const_iterator i = state_num.find(dst); hash_map::const_iterator i = state_num.find(dst);
if (i == state_num.end()) // Ignore useless destinations. if (i == state_num.end()) // Ignore useless destinations.
continue; continue;
bdd tgba_condition = bddtrue; bdd tgba_condition = bddtrue;
is_initial_state = a->is_initial_state(dst); is_initial_state = a->is_initial_state(dst);
if (!a->get_artificial_initial_state() && is_initial_state) if (!a->get_artificial_initial_state() && is_initial_state)
tgba_condition = a->get_state_condition(dst); tgba_condition = a->get_state_condition(dst);
bool is_accepting_state = a->is_accepting_state(dst); bool is_accepting_state = a->is_accepting_state(dst);
bool is_livelock_accepting_state = bool is_livelock_accepting_state =
a->is_livelock_accepting_state(dst); a->is_livelock_accepting_state(dst);
state_ta_explicit* new_dst = state_ta_explicit* new_dst =
new state_ta_explicit new state_ta_explicit
(result_tgba->state_from_number(i->second), (result_tgba->state_from_number(i->second),
tgba_condition, is_initial_state, tgba_condition, is_initial_state,
is_accepting_state, is_accepting_state,
is_livelock_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) if (ta_dst != new_dst)
{ {
delete new_dst; delete new_dst;
} }
else if (a->get_artificial_initial_state()) else if (a->get_artificial_initial_state())
{ {
if (a->get_artificial_initial_state() == dst) if (a->get_artificial_initial_state() == dst)
result->set_artificial_initial_state(new_dst); result->set_artificial_initial_state(new_dst);
} }
else if (is_initial_state) else if (is_initial_state)
result->add_to_initial_states_set(new_dst); result->add_to_initial_states_set(new_dst);
result->create_transition result->create_transition
(ta_src, succit->cond(), (ta_src, succit->cond(),
succit->acc(), succit->acc(),
ta_dst); ta_dst);
} }
delete succit; delete succit;
} }
} }
static partition_t static partition_t
@ -187,22 +187,22 @@ namespace spot
unsigned num_sets = ta_->acc().num_sets(); unsigned num_sets = ta_->acc().num_sets();
std::map<acc_cond::mark_t, bdd> m2b; std::map<acc_cond::mark_t, bdd> m2b;
int acc_vars = ta_->get_dict()->register_anonymous_variables(num_sets, int acc_vars = ta_->get_dict()->register_anonymous_variables(num_sets,
&m2b); &m2b);
auto mark_to_bdd = [&](acc_cond::mark_t m) -> bdd auto mark_to_bdd = [&](acc_cond::mark_t m) -> bdd
{ {
auto i = m2b.find(m); auto i = m2b.find(m);
if (i != m2b.end()) if (i != m2b.end())
return i->second; return i->second;
bdd res = bddtrue; bdd res = bddtrue;
for (unsigned n = 0; n < num_sets; ++n) for (unsigned n = 0; n < num_sets; ++n)
if (m.has(n)) if (m.has(n))
res &= bdd_ithvar(acc_vars + n); res &= bdd_ithvar(acc_vars + n);
else else
res &= bdd_nithvar(acc_vars + n); res &= bdd_nithvar(acc_vars + n);
m2b.emplace_hint(i, m, res); m2b.emplace_hint(i, m, res);
return res; return res;
}; };
partition_t cur_run; partition_t cur_run;
partition_t next_run; partition_t next_run;
@ -231,22 +231,22 @@ namespace spot
auto artificial_initial_state = ta_->get_artificial_initial_state(); auto artificial_initial_state = ta_->get_artificial_initial_state();
for (it = states_set.begin(); it != states_set.end(); ++it) for (it = states_set.begin(); it != states_set.end(); ++it)
{ {
const state* s = *it; const state* s = *it;
if (s == artificial_initial_state) if (s == artificial_initial_state)
I->insert(s); I->insert(s);
else if (!artificial_initial_state && ta_->is_initial_state(s)) else if (!artificial_initial_state && ta_->is_initial_state(s))
I->insert(s); I->insert(s);
else if (ta_->is_livelock_accepting_state(s) else if (ta_->is_livelock_accepting_state(s)
&& ta_->is_accepting_state(s)) && ta_->is_accepting_state(s))
G_F->insert(s); G_F->insert(s);
else if (ta_->is_accepting_state(s)) else if (ta_->is_accepting_state(s))
F->insert(s); F->insert(s);
else if (ta_->is_livelock_accepting_state(s)) else if (ta_->is_livelock_accepting_state(s))
G->insert(s); G->insert(s);
else else
S->insert(s); S->insert(s);
} }
hash_map state_set_map; hash_map state_set_map;
@ -255,103 +255,103 @@ namespace spot
// Use bdd variables to number sets. set_num is the first variable // Use bdd variables to number sets. set_num is the first variable
// available. // available.
unsigned set_num = unsigned set_num =
ta_->get_dict()->register_anonymous_variables(size, &m2b); ta_->get_dict()->register_anonymous_variables(size, &m2b);
std::set<int> free_var; std::set<int> free_var;
for (unsigned i = set_num; i < set_num + size; ++i) for (unsigned i = set_num; i < set_num + size; ++i)
free_var.insert(i); free_var.insert(i);
std::map<int, int> used_var; std::map<int, int> used_var;
for (hash_set::const_iterator i = I->begin(); i != I->end(); ++i) for (hash_set::const_iterator i = I->begin(); i != I->end(); ++i)
{ {
hash_set* cI = new hash_set; hash_set* cI = new hash_set;
cI->insert(*i); cI->insert(*i);
done.push_back(cI); done.push_back(cI);
used_var[set_num] = 1; used_var[set_num] = 1;
free_var.erase(set_num); free_var.erase(set_num);
state_set_map[*i] = set_num; state_set_map[*i] = set_num;
++set_num; ++set_num;
} }
delete I; delete I;
if (!G->empty()) if (!G->empty())
{ {
unsigned s = G->size(); unsigned s = G->size();
unsigned num = set_num; unsigned num = set_num;
++set_num; ++set_num;
used_var[num] = s; used_var[num] = s;
free_var.erase(num); free_var.erase(num);
if (s > 1) if (s > 1)
cur_run.push_back(G); cur_run.push_back(G);
else else
done.push_back(G); done.push_back(G);
for (hash_set::const_iterator i = G->begin(); i != G->end(); ++i) for (hash_set::const_iterator i = G->begin(); i != G->end(); ++i)
state_set_map[*i] = num; state_set_map[*i] = num;
} }
else else
{ {
delete G; delete G;
} }
if (!F->empty()) if (!F->empty())
{ {
unsigned s = F->size(); unsigned s = F->size();
unsigned num = set_num; unsigned num = set_num;
++set_num; ++set_num;
used_var[num] = s; used_var[num] = s;
free_var.erase(num); free_var.erase(num);
if (s > 1) if (s > 1)
cur_run.push_back(F); cur_run.push_back(F);
else else
done.push_back(F); done.push_back(F);
for (hash_set::const_iterator i = F->begin(); i != F->end(); ++i) for (hash_set::const_iterator i = F->begin(); i != F->end(); ++i)
state_set_map[*i] = num; state_set_map[*i] = num;
} }
else else
{ {
delete F; delete F;
} }
if (!G_F->empty()) if (!G_F->empty())
{ {
unsigned s = G_F->size(); unsigned s = G_F->size();
unsigned num = set_num; unsigned num = set_num;
++set_num; ++set_num;
used_var[num] = s; used_var[num] = s;
free_var.erase(num); free_var.erase(num);
if (s > 1) if (s > 1)
cur_run.push_back(G_F); cur_run.push_back(G_F);
else else
done.push_back(G_F); done.push_back(G_F);
for (hash_set::const_iterator i = G_F->begin(); i != G_F->end(); ++i) for (hash_set::const_iterator i = G_F->begin(); i != G_F->end(); ++i)
state_set_map[*i] = num; state_set_map[*i] = num;
} }
else else
{ {
delete G_F; delete G_F;
} }
if (!S->empty()) if (!S->empty())
{ {
unsigned s = S->size(); unsigned s = S->size();
unsigned num = set_num; unsigned num = set_num;
++set_num; ++set_num;
used_var[num] = s; used_var[num] = s;
free_var.erase(num); free_var.erase(num);
if (s > 1) if (s > 1)
cur_run.push_back(S); cur_run.push_back(S);
else else
done.push_back(S); done.push_back(S);
for (hash_set::const_iterator i = S->begin(); i != S->end(); ++i) for (hash_set::const_iterator i = S->begin(); i != S->end(); ++i)
state_set_map[*i] = num; state_set_map[*i] = num;
} }
else else
{ {
delete S; delete S;
} }
// A bdd_states_map is a list of formulae (in a BDD form) // 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); bdd bdd_false_acceptance_condition = bdd_ithvar(num);
while (did_split) while (did_split)
{ {
did_split = false; did_split = false;
while (!cur_run.empty()) while (!cur_run.empty())
{ {
// Get a set to process. // Get a set to process.
hash_set* cur = cur_run.front(); hash_set* cur = cur_run.front();
cur_run.pop_front(); cur_run.pop_front();
trace trace
<< "processing " << format_hash_set(cur, ta_) << std::endl; << "processing " << format_hash_set(cur, ta_) << std::endl;
hash_set::iterator hi; hash_set::iterator hi;
bdd_states_map bdd_map; bdd_states_map bdd_map;
for (hi = cur->begin(); hi != cur->end(); ++hi) for (hi = cur->begin(); hi != cur->end(); ++hi)
{ {
const state* src = *hi; const state* src = *hi;
bdd f = bddfalse; bdd f = bddfalse;
ta_succ_iterator* si = ta_->succ_iter(src); ta_succ_iterator* si = ta_->succ_iter(src);
trace << "+src: " << src << std::endl; trace << "+src: " << src << std::endl;
for (si->first(); !si->done(); si->next()) for (si->first(); !si->done(); si->next())
{ {
const state* dst = si->dst(); const state* dst = si->dst();
hash_map::const_iterator i = state_set_map.find(dst); hash_map::const_iterator i = state_set_map.find(dst);
assert(i != state_set_map.end()); assert(i != state_set_map.end());
auto curacc = auto curacc =
mark_to_bdd(si->acc()); mark_to_bdd(si->acc());
f |= (bdd_ithvar(i->second) f |= (bdd_ithvar(i->second)
& si->cond() & curacc); & si->cond() & curacc);
trace trace
<< "+f: " << bdd_format_accset(ta_->get_dict(), f) << "+f: " << bdd_format_accset(ta_->get_dict(), f)
<< "\n -bdd_ithvar(i->second): " << "\n -bdd_ithvar(i->second): "
<< bdd_format_accset(ta_->get_dict(), << bdd_format_accset(ta_->get_dict(),
bdd_ithvar(i->second)) bdd_ithvar(i->second))
<< "\n -si->cond(): " << "\n -si->cond(): "
<< bdd_format_accset(ta_->get_dict(), << bdd_format_accset(ta_->get_dict(),
si->cond()) si->cond())
<< "\n -current_acceptance_conditions: " << "\n -current_acceptance_conditions: "
<< si->acc() << si->acc()
<< std::endl; << std::endl;
} }
delete si; delete si;
// Have we already seen this formula ? // Have we already seen this formula ?
bdd_states_map::iterator bsi = bdd_map.find(f); bdd_states_map::iterator bsi = bdd_map.find(f);
if (bsi == bdd_map.end()) if (bsi == bdd_map.end())
{ {
// No, create a new set. // No, create a new set.
hash_set* new_set = new hash_set; hash_set* new_set = new hash_set;
new_set->insert(src); new_set->insert(src);
bdd_map[f] = new_set; bdd_map[f] = new_set;
} }
else else
{ {
// Yes, add the current state to the set. // Yes, add the current state to the set.
bsi->second->insert(src); bsi->second->insert(src);
} }
} }
bdd_states_map::iterator bsi = bdd_map.begin(); bdd_states_map::iterator bsi = bdd_map.begin();
if (bdd_map.size() == 1) if (bdd_map.size() == 1)
{ {
// The set was not split. // The set was not split.
trace trace
<< "set " << format_hash_set(bsi->second, ta_) << "set " << format_hash_set(bsi->second, ta_)
<< " was not split" << std::endl; << " was not split" << std::endl;
next_run.push_back(bsi->second); next_run.push_back(bsi->second);
} }
else else
{ {
did_split = true; did_split = true;
for (; bsi != bdd_map.end(); ++bsi) for (; bsi != bdd_map.end(); ++bsi)
{ {
hash_set* set = bsi->second; hash_set* set = bsi->second;
// Free the number associated to these states. // Free the number associated to these states.
unsigned num = state_set_map[*set->begin()]; unsigned num = state_set_map[*set->begin()];
assert(used_var.find(num) != used_var.end()); assert(used_var.find(num) != used_var.end());
unsigned left = (used_var[num] -= set->size()); unsigned left = (used_var[num] -= set->size());
// Make sure LEFT does not become negative // Make sure LEFT does not become negative
// (hence bigger than SIZE when read as unsigned) // (hence bigger than SIZE when read as unsigned)
assert(left < size); assert(left < size);
if (left == 0) if (left == 0)
{ {
used_var.erase(num); used_var.erase(num);
free_var.insert(num); free_var.insert(num);
} }
// Pick a free number // Pick a free number
assert(!free_var.empty()); assert(!free_var.empty());
num = *free_var.begin(); num = *free_var.begin();
free_var.erase(free_var.begin()); free_var.erase(free_var.begin());
used_var[num] = set->size(); used_var[num] = set->size();
for (hash_set::iterator hit = set->begin(); for (hash_set::iterator hit = set->begin();
hit != set->end(); ++hit) hit != set->end(); ++hit)
state_set_map[*hit] = num; state_set_map[*hit] = num;
// Trivial sets can't be splitted any further. // Trivial sets can't be splitted any further.
if (set->size() == 1) if (set->size() == 1)
{ {
trace trace
<< "set " << format_hash_set(set, ta_) << "set " << format_hash_set(set, ta_)
<< " is minimal" << std::endl; << " is minimal" << std::endl;
done.push_back(set); done.push_back(set);
} }
else else
{ {
trace trace
<< "set " << format_hash_set(set, ta_) << "set " << format_hash_set(set, ta_)
<< " should be processed further" << std::endl; << " should be processed further" << std::endl;
next_run.push_back(set); next_run.push_back(set);
} }
} }
} }
delete cur; delete cur;
} }
if (did_split) if (did_split)
trace trace
<< "splitting did occur during this pass." << std::endl; << "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); done.splice(done.end(), cur_run);
#ifdef TRACE #ifdef TRACE
trace << "Final partition: "; trace << "Final partition: ";
for (partition_t::const_iterator i = done.begin(); i != done.end(); ++i) 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; trace << std::endl;
#endif #endif

View file

@ -51,17 +51,17 @@ namespace spot
{ {
if (artificial_livelock_acc_state) 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); testing_automata->add_state(artificial_livelock_acc_state);
// unique artificial_livelock_acc_state // unique artificial_livelock_acc_state
assert(artificial_livelock_acc_state_added assert(artificial_livelock_acc_state_added
== artificial_livelock_acc_state); == artificial_livelock_acc_state);
(void)artificial_livelock_acc_state_added; (void)artificial_livelock_acc_state_added;
artificial_livelock_acc_state->set_livelock_accepting_state(true); artificial_livelock_acc_state->set_livelock_accepting_state(true);
artificial_livelock_acc_state->free_transitions(); artificial_livelock_acc_state->free_transitions();
} }
ta::states_set_t states_set = testing_automata->get_states_set(); ta::states_set_t states_set = testing_automata->get_states_set();
ta::states_set_t::iterator it; ta::states_set_t::iterator it;
@ -70,86 +70,86 @@ namespace spot
new state_ta_explicit::transitions; new state_ta_explicit::transitions;
for (it = states_set.begin(); it != states_set.end(); ++it) for (it = states_set.begin(); it != states_set.end(); ++it)
{ {
auto source = const_cast<state_ta_explicit*> auto source = const_cast<state_ta_explicit*>
(static_cast<const state_ta_explicit*>(*it)); (static_cast<const state_ta_explicit*>(*it));
transitions_to_livelock_states->clear(); transitions_to_livelock_states->clear();
state_ta_explicit::transitions* trans = source->get_transitions(); state_ta_explicit::transitions* trans = source->get_transitions();
state_ta_explicit::transitions::iterator it_trans; state_ta_explicit::transitions::iterator it_trans;
if (trans) if (trans)
for (it_trans = trans->begin(); it_trans != trans->end();) for (it_trans = trans->begin(); it_trans != trans->end();)
{ {
auto dest = const_cast<state_ta_explicit*>((*it_trans)->dest); auto dest = const_cast<state_ta_explicit*>((*it_trans)->dest);
state_ta_explicit::transitions* dest_trans = state_ta_explicit::transitions* dest_trans =
dest->get_transitions(); dest->get_transitions();
bool dest_trans_empty = !dest_trans || dest_trans->empty(); bool dest_trans_empty = !dest_trans || dest_trans->empty();
//select transitions where a destination is a livelock state //select transitions where a destination is a livelock state
// which isn't a Buchi accepting state and has successors // which isn't a Buchi accepting state and has successors
if (dest->is_livelock_accepting_state() if (dest->is_livelock_accepting_state()
&& (!dest->is_accepting_state()) && (!dest_trans_empty)) && (!dest->is_accepting_state()) && (!dest_trans_empty))
transitions_to_livelock_states->push_front(*it_trans); transitions_to_livelock_states->push_front(*it_trans);
// optimization to have, after minimization, an unique // optimization to have, after minimization, an unique
// livelock state which has no successors // livelock state which has no successors
if (dest->is_livelock_accepting_state() && (dest_trans_empty)) if (dest->is_livelock_accepting_state() && (dest_trans_empty))
dest->set_accepting_state(false); dest->set_accepting_state(false);
++it_trans; ++it_trans;
} }
if (transitions_to_livelock_states) if (transitions_to_livelock_states)
{ {
state_ta_explicit::transitions::iterator it_trans; state_ta_explicit::transitions::iterator it_trans;
for (it_trans = transitions_to_livelock_states->begin(); for (it_trans = transitions_to_livelock_states->begin();
it_trans != transitions_to_livelock_states->end(); it_trans != transitions_to_livelock_states->end();
++it_trans) ++it_trans)
{ {
if (artificial_livelock_acc_state) if (artificial_livelock_acc_state)
{ {
testing_automata->create_transition testing_automata->create_transition
(source, (source,
(*it_trans)->condition, (*it_trans)->condition,
(*it_trans)->acceptance_conditions, (*it_trans)->acceptance_conditions,
artificial_livelock_acc_state, true); artificial_livelock_acc_state, true);
} }
else else
{ {
testing_automata->create_transition testing_automata->create_transition
(source, (source,
(*it_trans)->condition, (*it_trans)->condition,
(*it_trans)->acceptance_conditions, (*it_trans)->acceptance_conditions,
((*it_trans)->dest)->stuttering_reachable_livelock, ((*it_trans)->dest)->stuttering_reachable_livelock,
true); true);
} }
} }
} }
} }
delete transitions_to_livelock_states; delete transitions_to_livelock_states;
for (it = states_set.begin(); it != states_set.end(); ++it) for (it = states_set.begin(); it != states_set.end(); ++it)
{ {
state_ta_explicit* state = static_cast<state_ta_explicit*> (*it); state_ta_explicit* state = static_cast<state_ta_explicit*> (*it);
state_ta_explicit::transitions* state_trans = state_ta_explicit::transitions* state_trans =
(state)->get_transitions(); (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() if (state->is_livelock_accepting_state()
&& (!state->is_accepting_state()) && (!state_trans_empty)) && (!state->is_accepting_state()) && (!state_trans_empty))
state->set_livelock_accepting_state(false); state->set_livelock_accepting_state(false);
} }
} }
static void static void
compute_livelock_acceptance_states(const ta_explicit_ptr& testing_aut, compute_livelock_acceptance_states(const ta_explicit_ptr& testing_aut,
bool single_pass_emptiness_check, bool single_pass_emptiness_check,
state_ta_explicit* state_ta_explicit*
artificial_livelock_acc_state) artificial_livelock_acc_state)
{ {
// We use five main data in this algorithm: // We use five main data in this algorithm:
// * sscc: a stack of strongly stuttering-connected components (SSCC) // * sscc: a stack of strongly stuttering-connected components (SSCC)
@ -177,234 +177,234 @@ namespace spot
std::stack<const state*> init_set; std::stack<const state*> init_set;
for (auto s: testing_aut->get_initial_states_set()) for (auto s: testing_aut->get_initial_states_set())
init_set.push(s); init_set.push(s);
while (!init_set.empty()) while (!init_set.empty())
{ {
// Setup depth-first search from initial states. // Setup depth-first search from initial states.
{ {
auto init = down_cast<const state_ta_explicit*> (init_set.top()); auto init = down_cast<const state_ta_explicit*> (init_set.top());
init_set.pop(); init_set.pop();
if (!h.emplace(init, num + 1).second) if (!h.emplace(init, num + 1).second)
{ {
init->destroy(); init->destroy();
continue; continue;
} }
sscc.push(++num); sscc.push(++num);
arc.push(0U); arc.push(0U);
sscc.top().is_accepting sscc.top().is_accepting
= testing_aut->is_accepting_state(init); = testing_aut->is_accepting_state(init);
twa_succ_iterator* iter = testing_aut->succ_iter(init); twa_succ_iterator* iter = testing_aut->succ_iter(init);
iter->first(); iter->first();
todo.emplace(init, iter); todo.emplace(init, iter);
} }
while (!todo.empty()) while (!todo.empty())
{ {
auto curr = todo.top().first; auto curr = todo.top().first;
auto i = h.find(curr); auto i = h.find(curr);
// If we have reached a dead component, ignore it. // If we have reached a dead component, ignore it.
if (i != h.end() && i->second == -1) if (i != h.end() && i->second == -1)
{ {
todo.pop(); todo.pop();
continue; continue;
} }
// We are looking at the next successor in SUCC. // We are looking at the next successor in SUCC.
twa_succ_iterator* succ = todo.top().second; twa_succ_iterator* succ = todo.top().second;
// If there is no more successor, backtrack. // If there is no more successor, backtrack.
if (succ->done()) if (succ->done())
{ {
// We have explored all successors of state CURR. // We have explored all successors of state CURR.
// Backtrack TODO. // Backtrack TODO.
todo.pop(); todo.pop();
// fill rem with any component removed, // fill rem with any component removed,
assert(i != h.end()); assert(i != h.end());
sscc.rem().push_front(curr); sscc.rem().push_front(curr);
// When backtracking the root of an SSCC, we must also // When backtracking the root of an SSCC, we must also
// remove that SSCC from the ROOT stacks. We must // remove that SSCC from the ROOT stacks. We must
// discard from H all reachable states from this SSCC. // discard from H all reachable states from this SSCC.
assert(!sscc.empty()); assert(!sscc.empty());
if (sscc.top().index == i->second) if (sscc.top().index == i->second)
{ {
// removing states // removing states
bool is_livelock_accepting_sscc = (sscc.rem().size() > 1) bool is_livelock_accepting_sscc = (sscc.rem().size() > 1)
&& ((sscc.top().is_accepting) || && ((sscc.top().is_accepting) ||
(testing_aut->acc(). (testing_aut->acc().
accepting(sscc.top().condition))); accepting(sscc.top().condition)));
trace << "*** sscc.size() = ***" << sscc.size() << '\n'; trace << "*** sscc.size() = ***" << sscc.size() << '\n';
for (auto j: sscc.rem()) for (auto j: sscc.rem())
{ {
h[j] = -1; h[j] = -1;
if (is_livelock_accepting_sscc) if (is_livelock_accepting_sscc)
{ {
// if it is an accepting sscc add the state to // if it is an accepting sscc add the state to
// G (=the livelock-accepting states set) // G (=the livelock-accepting states set)
trace << "*** sscc.size() > 1: states: ***" trace << "*** sscc.size() > 1: states: ***"
<< testing_aut->format_state(j) << testing_aut->format_state(j)
<< '\n'; << '\n';
auto livelock_accepting_state = auto livelock_accepting_state =
const_cast<state_ta_explicit*> const_cast<state_ta_explicit*>
(down_cast<const state_ta_explicit*>(j)); (down_cast<const state_ta_explicit*>(j));
livelock_accepting_state-> livelock_accepting_state->
set_livelock_accepting_state(true); set_livelock_accepting_state(true);
if (single_pass_emptiness_check) if (single_pass_emptiness_check)
{ {
livelock_accepting_state livelock_accepting_state
->set_accepting_state(true); ->set_accepting_state(true);
livelock_accepting_state livelock_accepting_state
->stuttering_reachable_livelock ->stuttering_reachable_livelock
= livelock_accepting_state; = livelock_accepting_state;
} }
} }
} }
assert(!arc.empty()); assert(!arc.empty());
sscc.pop(); sscc.pop();
arc.pop(); arc.pop();
} }
// automata reduction // automata reduction
testing_aut->delete_stuttering_and_hole_successors(curr); testing_aut->delete_stuttering_and_hole_successors(curr);
delete succ; delete succ;
// Do not delete CURR: it is a key in H. // Do not delete CURR: it is a key in H.
continue; continue;
} }
// Fetch the values destination state we are interested in... // Fetch the values destination state we are interested in...
auto dest = succ->dst(); auto dest = succ->dst();
auto acc_cond = succ->acc(); auto acc_cond = succ->acc();
// ... and point the iterator to the next successor, for // ... and point the iterator to the next successor, for
// the next iteration. // the next iteration.
succ->next(); succ->next();
// We do not need SUCC from now on. // We do not need SUCC from now on.
// Are we going to a new state through a stuttering transition? // Are we going to a new state through a stuttering transition?
bool is_stuttering_transition = bool is_stuttering_transition =
testing_aut->get_state_condition(curr) testing_aut->get_state_condition(curr)
== testing_aut->get_state_condition(dest); == testing_aut->get_state_condition(dest);
auto id = h.find(dest); auto id = h.find(dest);
// Is this a new state? // Is this a new state?
if (id == h.end()) if (id == h.end())
{ {
if (!is_stuttering_transition) if (!is_stuttering_transition)
{ {
init_set.push(dest); init_set.push(dest);
dest->destroy(); dest->destroy();
continue; continue;
} }
// Number it, stack it, and register its successors // Number it, stack it, and register its successors
// for later processing. // for later processing.
h[dest] = ++num; h[dest] = ++num;
sscc.push(num); sscc.push(num);
arc.push(acc_cond); arc.push(acc_cond);
sscc.top().is_accepting = sscc.top().is_accepting =
testing_aut->is_accepting_state(dest); testing_aut->is_accepting_state(dest);
twa_succ_iterator* iter = testing_aut->succ_iter(dest); twa_succ_iterator* iter = testing_aut->succ_iter(dest);
iter->first(); iter->first();
todo.emplace(dest, iter); todo.emplace(dest, iter);
continue; continue;
} }
dest->destroy(); dest->destroy();
// If we have reached a dead component, ignore it. // If we have reached a dead component, ignore it.
if (id->second == -1) if (id->second == -1)
continue; continue;
trace << "***compute_livelock_acceptance_states: CYCLE***\n"; trace << "***compute_livelock_acceptance_states: CYCLE***\n";
if (!curr->compare(id->first)) if (!curr->compare(id->first))
{ {
auto self_loop_state = const_cast<state_ta_explicit*> auto self_loop_state = const_cast<state_ta_explicit*>
(down_cast<const state_ta_explicit*>(curr)); (down_cast<const state_ta_explicit*>(curr));
assert(self_loop_state); assert(self_loop_state);
if (testing_aut->is_accepting_state(self_loop_state) if (testing_aut->is_accepting_state(self_loop_state)
|| (testing_aut->acc().accepting(acc_cond))) || (testing_aut->acc().accepting(acc_cond)))
{ {
self_loop_state->set_livelock_accepting_state(true); self_loop_state->set_livelock_accepting_state(true);
if (single_pass_emptiness_check) if (single_pass_emptiness_check)
{ {
self_loop_state->set_accepting_state(true); self_loop_state->set_accepting_state(true);
self_loop_state->stuttering_reachable_livelock self_loop_state->stuttering_reachable_livelock
= self_loop_state; = self_loop_state;
} }
} }
trace trace
<< "***compute_livelock_acceptance_states: CYCLE: " << "***compute_livelock_acceptance_states: CYCLE: "
<< "self_loop_state***\n"; << "self_loop_state***\n";
} }
// Now this is the most interesting case. We have reached a // Now this is the most interesting case. We have reached a
// state S1 which is already part of a non-dead SSCC. Any such // state S1 which is already part of a non-dead SSCC. Any such
// non-dead SSCC has necessarily been crossed by our path to // non-dead SSCC has necessarily been crossed by our path to
// this state: there is a state S2 in our path which belongs // this state: there is a state S2 in our path which belongs
// to this SSCC too. We are going to merge all states between // to this SSCC too. We are going to merge all states between
// this S1 and S2 into this SSCC. // this S1 and S2 into this SSCC.
// //
// This merge is easy to do because the order of the SSCC in // 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 // ROOT is ascending: we just have to merge all SSCCs from the
// top of ROOT that have an index greater to the one of // top of ROOT that have an index greater to the one of
// the SSCC of S2 (called the "threshold"). // the SSCC of S2 (called the "threshold").
int threshold = id->second; int threshold = id->second;
std::list<const state*> rem; std::list<const state*> rem;
bool acc = false; bool acc = false;
while (threshold < sscc.top().index) while (threshold < sscc.top().index)
{ {
assert(!sscc.empty()); assert(!sscc.empty());
assert(!arc.empty()); assert(!arc.empty());
acc |= sscc.top().is_accepting; acc |= sscc.top().is_accepting;
acc_cond |= sscc.top().condition; acc_cond |= sscc.top().condition;
acc_cond |= arc.top(); acc_cond |= arc.top();
rem.splice(rem.end(), sscc.rem()); rem.splice(rem.end(), sscc.rem());
sscc.pop(); sscc.pop();
arc.pop(); arc.pop();
} }
// Note that we do not always have // Note that we do not always have
// threshold == sscc.top().index // threshold == sscc.top().index
// after this loop, the SSCC whose index is threshold might have // after this loop, the SSCC whose index is threshold might have
// been merged with a lower SSCC. // been merged with a lower SSCC.
// Accumulate all acceptance conditions into the merged SSCC. // Accumulate all acceptance conditions into the merged SSCC.
sscc.top().is_accepting |= acc; sscc.top().is_accepting |= acc;
sscc.top().condition |= acc_cond; 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) if (artificial_livelock_acc_state || single_pass_emptiness_check)
transform_to_single_pass_automaton(testing_aut, transform_to_single_pass_automaton(testing_aut,
artificial_livelock_acc_state); artificial_livelock_acc_state);
} }
ta_explicit_ptr ta_explicit_ptr
build_ta(const ta_explicit_ptr& ta, bdd atomic_propositions_set_, build_ta(const ta_explicit_ptr& ta, bdd atomic_propositions_set_,
bool degeneralized, bool degeneralized,
bool single_pass_emptiness_check, bool single_pass_emptiness_check,
bool artificial_livelock_state_mode, bool artificial_livelock_state_mode,
bool no_livelock) bool no_livelock)
{ {
std::stack<state_ta_explicit*> todo; std::stack<state_ta_explicit*> todo;
@ -414,140 +414,140 @@ namespace spot
auto tgba_init_state = tgba_->get_init_state(); auto tgba_init_state = tgba_->get_init_state();
bdd tgba_condition = [&]() bdd tgba_condition = [&]()
{ {
bdd cond = bddfalse; bdd cond = bddfalse;
for (auto i: tgba_->succ(tgba_init_state)) for (auto i: tgba_->succ(tgba_init_state))
cond |= i->cond(); cond |= i->cond();
return cond; return cond;
}(); }();
bool is_acc = false; bool is_acc = false;
if (degeneralized) if (degeneralized)
{ {
twa_succ_iterator* it = tgba_->succ_iter(tgba_init_state); twa_succ_iterator* it = tgba_->succ_iter(tgba_init_state);
it->first(); it->first();
if (!it->done()) if (!it->done())
is_acc = it->acc() != 0U; is_acc = it->acc() != 0U;
delete it; delete it;
} }
bdd satone_tgba_condition; bdd satone_tgba_condition;
while ((satone_tgba_condition = bdd_satoneset(tgba_condition, while ((satone_tgba_condition = bdd_satoneset(tgba_condition,
atomic_propositions_set_, atomic_propositions_set_,
bddtrue)) != bddfalse) bddtrue)) != bddfalse)
{ {
tgba_condition -= satone_tgba_condition; tgba_condition -= satone_tgba_condition;
state_ta_explicit* init_state = new state_ta_explicit* init_state = new
state_ta_explicit(tgba_init_state->clone(), state_ta_explicit(tgba_init_state->clone(),
satone_tgba_condition, true, is_acc); satone_tgba_condition, true, is_acc);
state_ta_explicit* s = ta->add_state(init_state); state_ta_explicit* s = ta->add_state(init_state);
assert(s == init_state); assert(s == init_state);
ta->add_to_initial_states_set(s); ta->add_to_initial_states_set(s);
todo.push(init_state); todo.push(init_state);
} }
tgba_init_state->destroy(); tgba_init_state->destroy();
while (!todo.empty()) while (!todo.empty())
{ {
state_ta_explicit* source = todo.top(); state_ta_explicit* source = todo.top();
todo.pop(); todo.pop();
twa_succ_iterator* twa_succ_it = twa_succ_iterator* twa_succ_it =
tgba_->succ_iter(source->get_tgba_state()); tgba_->succ_iter(source->get_tgba_state());
for (twa_succ_it->first(); !twa_succ_it->done(); for (twa_succ_it->first(); !twa_succ_it->done();
twa_succ_it->next()) twa_succ_it->next())
{ {
const state* tgba_state = twa_succ_it->dst(); const state* tgba_state = twa_succ_it->dst();
bdd tgba_condition = twa_succ_it->cond(); bdd tgba_condition = twa_succ_it->cond();
acc_cond::mark_t tgba_acceptance_conditions = acc_cond::mark_t tgba_acceptance_conditions =
twa_succ_it->acc(); twa_succ_it->acc();
bdd satone_tgba_condition; bdd satone_tgba_condition;
while ((satone_tgba_condition = while ((satone_tgba_condition =
bdd_satoneset(tgba_condition, bdd_satoneset(tgba_condition,
atomic_propositions_set_, bddtrue)) atomic_propositions_set_, bddtrue))
!= bddfalse) != bddfalse)
{ {
tgba_condition -= satone_tgba_condition; tgba_condition -= satone_tgba_condition;
bdd all_props = bddtrue; bdd all_props = bddtrue;
bdd dest_condition; bdd dest_condition;
bool is_acc = false; bool is_acc = false;
if (degeneralized) if (degeneralized)
{ {
twa_succ_iterator* it = tgba_->succ_iter(tgba_state); twa_succ_iterator* it = tgba_->succ_iter(tgba_state);
it->first(); it->first();
if (!it->done()) if (!it->done())
is_acc = it->acc() != 0U; is_acc = it->acc() != 0U;
delete it; delete it;
} }
if (satone_tgba_condition == source->get_tgba_condition()) if (satone_tgba_condition == source->get_tgba_condition())
while ((dest_condition = while ((dest_condition =
bdd_satoneset(all_props, bdd_satoneset(all_props,
atomic_propositions_set_, bddtrue)) atomic_propositions_set_, bddtrue))
!= bddfalse) != bddfalse)
{ {
all_props -= dest_condition; all_props -= dest_condition;
state_ta_explicit* new_dest = state_ta_explicit* new_dest =
new state_ta_explicit(tgba_state->clone(), new state_ta_explicit(tgba_state->clone(),
dest_condition, false, is_acc); dest_condition, false, is_acc);
state_ta_explicit* dest = ta->add_state(new_dest); state_ta_explicit* dest = ta->add_state(new_dest);
if (dest != new_dest) if (dest != new_dest)
{ {
// the state dest already exists in the automaton // the state dest already exists in the automaton
new_dest->get_tgba_state()->destroy(); new_dest->get_tgba_state()->destroy();
delete new_dest; delete new_dest;
} }
else else
{ {
todo.push(dest); todo.push(dest);
} }
bdd cs = bdd_setxor(source->get_tgba_condition(), bdd cs = bdd_setxor(source->get_tgba_condition(),
dest->get_tgba_condition()); dest->get_tgba_condition());
ta->create_transition(source, cs, ta->create_transition(source, cs,
tgba_acceptance_conditions, dest); tgba_acceptance_conditions, dest);
} }
} }
tgba_state->destroy(); tgba_state->destroy();
} }
delete twa_succ_it; delete twa_succ_it;
} }
if (no_livelock) if (no_livelock)
return ta; return ta;
state_ta_explicit* artificial_livelock_acc_state = nullptr; state_ta_explicit* artificial_livelock_acc_state = nullptr;
trace << "*** build_ta: artificial_livelock_acc_state_mode = ***" 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) if (artificial_livelock_state_mode)
{ {
single_pass_emptiness_check = true; single_pass_emptiness_check = true;
artificial_livelock_acc_state = artificial_livelock_acc_state =
new state_ta_explicit(ta->get_tgba()->get_init_state(), bddtrue, new state_ta_explicit(ta->get_tgba()->get_init_state(), bddtrue,
false, false, true, nullptr); false, false, true, nullptr);
trace trace
<< "*** build_ta: artificial_livelock_acc_state = ***" << "*** build_ta: artificial_livelock_acc_state = ***"
<< artificial_livelock_acc_state << std::endl; << artificial_livelock_acc_state << std::endl;
} }
compute_livelock_acceptance_states(ta, single_pass_emptiness_check, compute_livelock_acceptance_states(ta, single_pass_emptiness_check,
artificial_livelock_acc_state); artificial_livelock_acc_state);
return ta; return ta;
} }
} }
ta_explicit_ptr ta_explicit_ptr
tgba_to_ta(const const_twa_ptr& tgba_, bdd atomic_propositions_set_, tgba_to_ta(const const_twa_ptr& tgba_, bdd atomic_propositions_set_,
bool degeneralized, bool artificial_initial_state_mode, bool degeneralized, bool artificial_initial_state_mode,
bool single_pass_emptiness_check, bool single_pass_emptiness_check,
bool artificial_livelock_state_mode, bool artificial_livelock_state_mode,
bool no_livelock) bool no_livelock)
{ {
ta_explicit_ptr ta; ta_explicit_ptr ta;
@ -555,10 +555,10 @@ namespace spot
if (artificial_initial_state_mode) if (artificial_initial_state_mode)
{ {
state_ta_explicit* artificial_init_state = 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(), ta = make_ta_explicit(tgba_, tgba_->acc().num_sets(),
artificial_init_state); artificial_init_state);
} }
else else
{ {
@ -568,8 +568,8 @@ namespace spot
// build ta automaton // build ta automaton
build_ta(ta, atomic_propositions_set_, degeneralized, build_ta(ta, atomic_propositions_set_, degeneralized,
single_pass_emptiness_check, artificial_livelock_state_mode, single_pass_emptiness_check, artificial_livelock_state_mode,
no_livelock); no_livelock);
// (degeneralized=true) => TA // (degeneralized=true) => TA
if (degeneralized) if (degeneralized)
@ -589,8 +589,8 @@ namespace spot
state_ta_explicit::transitions::iterator it_trans; state_ta_explicit::transitions::iterator it_trans;
for (it_trans = trans->begin(); it_trans != trans->end(); for (it_trans = trans->begin(); it_trans != trans->end();
++it_trans) ++it_trans)
(*it_trans)->acceptance_conditions = ta->acc().all_sets(); (*it_trans)->acceptance_conditions = ta->acc().all_sets();
state->set_accepting_state(false); state->set_accepting_state(false);
} }
@ -604,11 +604,11 @@ namespace spot
{ {
auto tgba_init_state = tgba_->get_init_state(); auto tgba_init_state = tgba_->get_init_state();
auto artificial_init_state = new state_ta_explicit(tgba_init_state->clone(), auto artificial_init_state = new state_ta_explicit(tgba_init_state->clone(),
bddfalse, true); bddfalse, true);
tgba_init_state->destroy(); tgba_init_state->destroy();
auto tgta = make_tgta_explicit(tgba_, tgba_->acc().num_sets(), 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 // build a Generalized TA automaton involving a single_pass_emptiness_check
// (without an artificial livelock state): // (without an artificial livelock state):
@ -625,14 +625,14 @@ namespace spot
initial_states_iter->first(); initial_states_iter->first();
if (initial_states_iter->done()) if (initial_states_iter->done())
{ {
delete initial_states_iter; delete initial_states_iter;
return tgta; return tgta;
} }
bdd first_state_condition = initial_states_iter->cond(); bdd first_state_condition = initial_states_iter->cond();
delete initial_states_iter; delete initial_states_iter;
bdd bdd_stutering_transition = bdd_setxor(first_state_condition, 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) for (it = states_set.begin(); it != states_set.end(); ++it)
{ {
@ -645,13 +645,13 @@ namespace spot
if (trans_empty || state->is_accepting_state()) if (trans_empty || state->is_accepting_state())
{ {
ta->create_transition(state, bdd_stutering_transition, 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())) if (state->compare(ta->get_artificial_initial_state()))
ta->create_transition(state, bdd_stutering_transition, ta->create_transition(state, bdd_stutering_transition,
0U, state); 0U, state);
state->set_livelock_accepting_state(false); state->set_livelock_accepting_state(false);
state->set_accepting_state(false); state->set_accepting_state(false);

View file

@ -83,11 +83,11 @@ namespace spot
/// TGBA \a tgba_to_convert. /// TGBA \a tgba_to_convert.
SPOT_API ta_explicit_ptr SPOT_API ta_explicit_ptr
tgba_to_ta(const const_twa_ptr& tgba_to_convert, bdd atomic_propositions_set, tgba_to_ta(const const_twa_ptr& tgba_to_convert, bdd atomic_propositions_set,
bool degeneralized = true, bool degeneralized = true,
bool artificial_initial_state_mode = true, bool artificial_initial_state_mode = true,
bool single_pass_emptiness_check = false, bool single_pass_emptiness_check = false,
bool artificial_livelock_state_mode = false, bool artificial_livelock_state_mode = false,
bool no_livelock = false); bool no_livelock = false);
/// \ingroup tgba_ta /// \ingroup tgba_ta
/// \brief Build a spot::tgta_explicit* (TGTA) from an LTL formula. /// \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. /// language as the TGBA \a tgba_to_convert.
SPOT_API tgta_explicit_ptr SPOT_API tgta_explicit_ptr
tgba_to_tgta(const const_twa_ptr& tgba_to_convert, tgba_to_tgta(const const_twa_ptr& tgba_to_convert,
bdd atomic_propositions_set); bdd atomic_propositions_set);
} }

View file

@ -31,9 +31,9 @@ namespace spot
atomic_prop_set res; atomic_prop_set res;
for (unsigned i = 0; i < n; ++i) for (unsigned i = 0; i < n; ++i)
{ {
std::ostringstream p; std::ostringstream p;
p << 'p' << i; p << 'p' << i;
res.insert(formula::ap(p.str())); res.insert(formula::ap(p.str()));
} }
return res; return res;
} }
@ -44,11 +44,11 @@ namespace spot
if (!s) if (!s)
s = new atomic_prop_set; s = new atomic_prop_set;
f.traverse([&](const formula& f) f.traverse([&](const formula& f)
{ {
if (f.is(op::ap)) if (f.is(op::ap))
s->insert(f); s->insert(f);
return false; return false;
}); });
return s; return s;
} }

View file

@ -65,7 +65,7 @@ namespace spot
// Check whether L(l) is a subset of L(g). // Check whether L(l) is a subset of L(g).
bool bool
language_containment_checker::contained(formula l, language_containment_checker::contained(formula l,
formula g) formula g)
{ {
if (l == g) if (l == g)
return true; return true;
@ -77,7 +77,7 @@ namespace spot
// Check whether L(!l) is a subset of L(g). // Check whether L(!l) is a subset of L(g).
bool bool
language_containment_checker::neg_contained(formula l, language_containment_checker::neg_contained(formula l,
formula g) formula g)
{ {
if (l == g) if (l == g)
return false; return false;
@ -92,7 +92,7 @@ namespace spot
// Check whether L(l) is a subset of L(!g). // Check whether L(l) is a subset of L(!g).
bool bool
language_containment_checker::contained_neg(formula l, language_containment_checker::contained_neg(formula l,
formula g) formula g)
{ {
if (l == g) if (l == g)
return false; return false;
@ -122,7 +122,7 @@ namespace spot
return &i->second; return &i->second;
auto e = ltl_to_tgba_fm(f, dict_, exprop_, symb_merge_, 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]; record_& r = translated_[f];
r.translation = e; r.translation = e;
return &r; return &r;

View file

@ -43,9 +43,9 @@ namespace spot
/// This class uses spot::ltl_to_tgba_fm to translate LTL /// This class uses spot::ltl_to_tgba_fm to translate LTL
/// formulae. See that function for the meaning of these options. /// formulae. See that function for the meaning of these options.
language_containment_checker(const bdd_dict_ptr& dict, bool exprop, language_containment_checker(const bdd_dict_ptr& dict, bool exprop,
bool symb_merge, bool symb_merge,
bool branching_postponement, bool branching_postponement,
bool fair_loop_approx); bool fair_loop_approx);
~language_containment_checker(); ~language_containment_checker();

View file

@ -37,94 +37,94 @@ namespace spot
std::ostringstream* sinks_; std::ostringstream* sinks_;
dot_printer(std::ostream& os, formula f) dot_printer(std::ostream& os, formula f)
: os_(os), sinks_(new std::ostringstream) : os_(os), sinks_(new std::ostringstream)
{ {
os_ << "digraph G {\n"; os_ << "digraph G {\n";
rec(f); rec(f);
os_ << " subgraph atoms {\n rank=sink;\n" os_ << " subgraph atoms {\n rank=sink;\n"
<< sinks_->str() << " }\n}\n"; << sinks_->str() << " }\n}\n";
} }
~dot_printer() ~dot_printer()
{ {
delete sinks_; delete sinks_;
} }
int rec(formula f) int rec(formula f)
{ {
auto i = node_.emplace(f, node_.size()); auto i = node_.emplace(f, node_.size());
int src = i.first->second; int src = i.first->second;
if (!i.second) if (!i.second)
return src; return src;
op o = f.kind(); op o = f.kind();
std::string str = (o == op::ap) ? f.ap_name() : f.kindstr(); std::string str = (o == op::ap) ? f.ap_name() : f.kindstr();
if (o == op::ap || f.is_constant()) if (o == op::ap || f.is_constant())
*sinks_ << " " << src << " [label=\"" *sinks_ << " " << src << " [label=\""
<< str << "\", shape=box];\n"; << str << "\", shape=box];\n";
else else
os_ << " " << src << " [label=\"" << str << "\"];\n"; os_ << " " << src << " [label=\"" << str << "\"];\n";
int childnum = 0; int childnum = 0;
switch (o) switch (o)
{ {
case op::ff: case op::ff:
case op::tt: case op::tt:
case op::eword: case op::eword:
case op::ap: case op::ap:
case op::Not: case op::Not:
case op::X: case op::X:
case op::F: case op::F:
case op::G: case op::G:
case op::Closure: case op::Closure:
case op::NegClosure: case op::NegClosure:
case op::NegClosureMarked: case op::NegClosureMarked:
case op::Or: case op::Or:
case op::OrRat: case op::OrRat:
case op::And: case op::And:
case op::AndRat: case op::AndRat:
case op::AndNLM: case op::AndNLM:
case op::Star: case op::Star:
case op::FStar: case op::FStar:
childnum = 0; // No number for children childnum = 0; // No number for children
break; break;
case op::Xor: case op::Xor:
case op::Implies: case op::Implies:
case op::Equiv: case op::Equiv:
case op::U: case op::U:
case op::R: case op::R:
case op::W: case op::W:
case op::M: case op::M:
case op::EConcat: case op::EConcat:
case op::EConcatMarked: case op::EConcatMarked:
case op::UConcat: case op::UConcat:
childnum = -2; // L and R markers childnum = -2; // L and R markers
break; break;
case op::Concat: case op::Concat:
case op::Fusion: case op::Fusion:
childnum = 1; // Numbered children childnum = 1; // Numbered children
break; break;
} }
for (auto c: f) for (auto c: f)
{ {
// Do not merge the next two lines, as there is no // Do not merge the next two lines, as there is no
// guarantee that rec will be called before we start // guarantee that rec will be called before we start
// printing the transition. // printing the transition.
int dst = rec(c); int dst = rec(c);
os_ << " " << src << " -> " << dst; os_ << " " << src << " -> " << dst;
if (childnum > 0) if (childnum > 0)
os_ << " [taillabel=\"" << childnum << "\"]"; os_ << " [taillabel=\"" << childnum << "\"]";
if (childnum == -2) if (childnum == -2)
os_ << " [taillabel=\"L\"]"; os_ << " [taillabel=\"L\"]";
else if (childnum == -1) else if (childnum == -1)
os_ << " [taillabel=\"R\"]"; os_ << " [taillabel=\"R\"]";
os_ << ";\n"; os_ << ";\n";
++childnum; ++childnum;
} }
return src; return src;
} }
}; };
} }

View file

@ -33,66 +33,66 @@ namespace spot
std::vector<formula> group; std::vector<formula> group;
auto start = arg; auto start = arg;
while (*start) while (*start)
{ {
while (*start == ' ' || *start == '\t') while (*start == ' ' || *start == '\t')
++start; ++start;
if (!*start) if (!*start)
break; break;
if (*start == ',') if (*start == ',')
{ {
std::string s = "unexpected ',' in "; std::string s = "unexpected ',' in ";
s += arg; s += arg;
throw std::invalid_argument(s); throw std::invalid_argument(s);
} }
if (*start == '"') if (*start == '"')
{ {
++start; ++start;
auto end = start; auto end = start;
while (*end && *end != '"') while (*end && *end != '"')
{ {
if (*end == '\\') if (*end == '\\')
++end; ++end;
++end; ++end;
} }
if (!*end) if (!*end)
{ {
std::string s = "missing closing '\"' in "; std::string s = "missing closing '\"' in ";
s += arg; s += arg;
throw std::invalid_argument(s); throw std::invalid_argument(s);
} }
std::string ap(start, end - start); std::string ap(start, end - start);
group.emplace_back(formula::ap(ap)); group.emplace_back(formula::ap(ap));
do do
++end; ++end;
while (*end == ' ' || *end == '\t'); while (*end == ' ' || *end == '\t');
if (*end && *end != ',') if (*end && *end != ',')
{ {
std::string s = "unexpected character '"; std::string s = "unexpected character '";
s += *end; s += *end;
s += "' in "; s += "' in ";
s += arg; s += arg;
throw std::invalid_argument(s); throw std::invalid_argument(s);
} }
if (*end == ',') if (*end == ',')
++end; ++end;
start = end; start = end;
} }
else else
{ {
auto end = start; auto end = start;
while (*end && *end != ',') while (*end && *end != ',')
++end; ++end;
auto rend = end; auto rend = end;
while (rend > start && (rend[-1] == ' ' || rend[-1] == '\t')) while (rend > start && (rend[-1] == ' ' || rend[-1] == '\t'))
--rend; --rend;
std::string ap(start, rend - start); std::string ap(start, rend - start);
group.emplace_back(formula::ap(ap)); group.emplace_back(formula::ap(ap));
if (*end == ',') if (*end == ',')
start = end + 1; start = end + 1;
else else
break; break;
} }
} }
return group; return group;
} }
} }
@ -126,16 +126,16 @@ namespace spot
for (auto& g: groups) for (auto& g: groups)
{ {
group.clear(); group.clear();
for (auto ap: g) for (auto ap: g)
if (s->find(ap) != s->end()) if (s->find(ap) != s->end())
group.push_back(ap); group.push_back(ap);
unsigned s = group.size(); unsigned s = group.size();
for (unsigned j = 0; j < s; ++j) for (unsigned j = 0; j < s; ++j)
for (unsigned k = j + 1; k < s; ++k) for (unsigned k = j + 1; k < s; ++k)
v.push_back(nand(group[j], group[k])); v.push_back(nand(group[j], group[k]));
}; };
delete s; delete s;
@ -143,15 +143,15 @@ namespace spot
} }
twa_graph_ptr exclusive_ap::constrain(const_twa_graph_ptr aut, 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. // Compute the support of the automaton.
bdd support = bddtrue; bdd support = bddtrue;
{ {
std::set<int> bdd_seen; std::set<int> bdd_seen;
for (auto& t: aut->edges()) for (auto& t: aut->edges())
if (bdd_seen.insert(t.cond.id()).second) if (bdd_seen.insert(t.cond.id()).second)
support &= bdd_support(t.cond); support &= bdd_support(t.cond);
} }
bdd restrict = bddtrue; bdd restrict = bddtrue;
@ -160,19 +160,19 @@ namespace spot
std::vector<bdd> group; std::vector<bdd> group;
for (auto& g: groups) for (auto& g: groups)
{ {
group.clear(); group.clear();
for (auto ap: g) for (auto ap: g)
{ {
int v = d->has_registered_proposition(ap, aut); int v = d->has_registered_proposition(ap, aut);
if (v >= 0) if (v >= 0)
group.push_back(bdd_nithvar(v)); group.push_back(bdd_nithvar(v));
} }
unsigned s = group.size(); unsigned s = group.size();
for (unsigned j = 0; j < s; ++j) for (unsigned j = 0; j < s; ++j)
for (unsigned k = j + 1; k < s; ++k) for (unsigned k = j + 1; k < s; ++k)
restrict &= group[j] | group[k]; restrict &= group[j] | group[k];
} }
twa_graph_ptr res = make_twa_graph(aut->get_dict()); twa_graph_ptr res = make_twa_graph(aut->get_dict());
@ -181,26 +181,26 @@ namespace spot
res->copy_acceptance_of(aut); res->copy_acceptance_of(aut);
if (simplify_guards) if (simplify_guards)
{ {
transform_accessible(aut, res, [&](unsigned, bdd& cond, transform_accessible(aut, res, [&](unsigned, bdd& cond,
acc_cond::mark_t&, unsigned) acc_cond::mark_t&, unsigned)
{ {
minato_isop isop(cond & restrict, minato_isop isop(cond & restrict,
cond | !restrict, cond | !restrict,
true); true);
bdd res = bddfalse; bdd res = bddfalse;
bdd cube = bddfalse; bdd cube = bddfalse;
while ((cube = isop.next()) != bddfalse) while ((cube = isop.next()) != bddfalse)
res |= cube; res |= cube;
cond = res; cond = res;
}); });
} }
else else
{ {
transform_accessible(aut, res, [&](unsigned, bdd& cond, transform_accessible(aut, res, [&](unsigned, bdd& cond,
acc_cond::mark_t&, unsigned) acc_cond::mark_t&, unsigned)
{ {
cond &= restrict; cond &= restrict;
}); });
} }
return res; return res;
} }

View file

@ -41,6 +41,6 @@ namespace spot
formula constrain(formula f) const; formula constrain(formula f) const;
twa_graph_ptr constrain(const_twa_graph_ptr aut, twa_graph_ptr constrain(const_twa_graph_ptr aut,
bool simplify_guards = false) const; bool simplify_guards = false) const;
}; };
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -30,14 +30,14 @@ namespace spot
{ {
int len = 0; int len = 0;
f.traverse([&len](const formula& x) f.traverse([&len](const formula& x)
{ {
auto s = x.size(); auto s = x.size();
if (s > 1) if (s > 1)
len += s - 1; len += s - 1;
else else
++len; ++len;
return false; return false;
}); });
return len; return len;
} }
@ -46,31 +46,31 @@ namespace spot
{ {
int len = 0; int len = 0;
f.traverse([&len](const formula& x) f.traverse([&len](const formula& x)
{ {
if (x.is_boolean()) if (x.is_boolean())
{ {
++len; ++len;
return true; return true;
} }
auto s = x.size(); auto s = x.size();
if (s > 2) if (s > 2)
{ {
int b = 0; int b = 0;
for (const auto& y: x) for (const auto& y: x)
if (y.is_boolean()) if (y.is_boolean())
++b; ++b;
len += s - b * 2 + 1; len += s - b * 2 + 1;
} }
else if (s > 1) else if (s > 1)
{ {
len += s - 1; len += s - 1;
} }
else else
{ {
++len; ++len;
} }
return false; return false;
}); });
return len; return len;
} }

View file

@ -58,25 +58,25 @@ namespace spot
case op::UConcat: case op::UConcat:
case op::Concat: case op::Concat:
case op::Fusion: case op::Fusion:
res = f; res = f;
break; break;
case op::NegClosure: case op::NegClosure:
res = formula::NegClosureMarked(f[0]); res = formula::NegClosureMarked(f[0]);
break; break;
case op::EConcat: case op::EConcat:
res = formula::EConcatMarked(f[0], f[1]); res = formula::EConcatMarked(f[0], f[1]);
break; break;
case op::Or: case op::Or:
case op::And: case op::And:
res = f.map([this](formula f) res = f.map([this](formula f)
{ {
return this->mark_concat_ops(f); return this->mark_concat_ops(f);
}); });
break; break;
case op::Xor: case op::Xor:
case op::Implies: case op::Implies:
case op::Equiv: case op::Equiv:
SPOT_UNIMPLEMENTED(); SPOT_UNIMPLEMENTED();
} }
markops_[f] = res; markops_[f] = res;
@ -95,7 +95,7 @@ namespace spot
auto recurse = [this](formula f) auto recurse = [this](formula f)
{ {
return this->simplify_mark(f); return this->simplify_mark(f);
}; };
formula res; formula res;
@ -119,58 +119,58 @@ namespace spot
case op::EConcat: case op::EConcat:
case op::EConcatMarked: case op::EConcatMarked:
case op::UConcat: case op::UConcat:
res = f; res = f;
break; break;
case op::Or: case op::Or:
res = f.map(recurse); res = f.map(recurse);
break; break;
case op::And: case op::And:
{ {
std::set<std::pair<formula, formula>> empairs; std::set<std::pair<formula, formula>> empairs;
std::set<formula> nmset; std::set<formula> nmset;
std::vector<formula> elist; std::vector<formula> elist;
std::vector<formula> nlist; std::vector<formula> nlist;
std::vector<formula> v; std::vector<formula> v;
for (auto c: f) for (auto c: f)
{ {
if (c.is(op::EConcatMarked)) if (c.is(op::EConcatMarked))
{ {
empairs.emplace(c[0], c[1]); empairs.emplace(c[0], c[1]);
v.push_back(c.map(recurse)); v.push_back(c.map(recurse));
} }
else if (c.is(op::EConcat)) else if (c.is(op::EConcat))
{ {
elist.push_back(c); elist.push_back(c);
} }
else if (c.is(op::NegClosureMarked)) else if (c.is(op::NegClosureMarked))
{ {
nmset.insert(c[0]); nmset.insert(c[0]);
v.push_back(c.map(recurse)); v.push_back(c.map(recurse));
} }
else if (c.is(op::NegClosure)) else if (c.is(op::NegClosure))
{ {
nlist.push_back(c); nlist.push_back(c);
} }
else else
{ {
v.push_back(c); v.push_back(c);
} }
} }
// Keep only the non-marked EConcat for which we // Keep only the non-marked EConcat for which we
// have not seen a similar EConcatMarked. // have not seen a similar EConcatMarked.
for (auto e: elist) for (auto e: elist)
if (empairs.find(std::make_pair(e[0], e[1])) if (empairs.find(std::make_pair(e[0], e[1]))
== empairs.end()) == empairs.end())
v.push_back(e); v.push_back(e);
// Keep only the non-marked NegClosure for which we // Keep only the non-marked NegClosure for which we
// have not seen a similar NegClosureMarked. // have not seen a similar NegClosureMarked.
for (auto n: nlist) for (auto n: nlist)
if (nmset.find(n[0]) == nmset.end()) if (nmset.find(n[0]) == nmset.end())
v.push_back(n); v.push_back(n);
res = formula::And(v); res = formula::And(v);
} }
break; break;
case op::Xor: case op::Xor:
case op::Implies: case op::Implies:
case op::Equiv: case op::Equiv:
@ -181,7 +181,7 @@ namespace spot
case op::FStar: case op::FStar:
case op::Concat: case op::Concat:
case op::Fusion: case op::Fusion:
SPOT_UNIMPLEMENTED(); SPOT_UNIMPLEMENTED();
} }
simpmark_[f] = res; simpmark_[f] = res;

View file

@ -37,12 +37,12 @@ namespace spot
formula substitute_ap(formula f, formula ap_src, formula ap_dst) formula substitute_ap(formula f, formula ap_src, formula ap_dst)
{ {
return f.map([&](formula f) return f.map([&](formula f)
{ {
if (f == ap_src) if (f == ap_src)
return ap_dst; return ap_dst;
else else
return substitute_ap(f, ap_src, ap_dst); return substitute_ap(f, ap_src, ap_dst);
}); });
} }
typedef std::vector<formula> vec; typedef std::vector<formula> vec;
@ -58,229 +58,229 @@ namespace spot
formula mutate(formula f) formula mutate(formula f)
{ {
auto recurse = [this](formula f) auto recurse = [this](formula f)
{ {
return this->mutate(f); return this->mutate(f);
}; };
switch (f.kind()) switch (f.kind())
{ {
case op::ff: case op::ff:
case op::tt: case op::tt:
case op::eword: case op::eword:
return f; return f;
case op::ap: case op::ap:
if (opts_ & Mut_Ap2Const) if (opts_ & Mut_Ap2Const)
{ {
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::tt(); return formula::tt();
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::ff(); return formula::ff();
} }
return f; return f;
case op::Not: case op::Not:
case op::X: case op::X:
case op::F: case op::F:
case op::G: case op::G:
if ((opts_ & Mut_Remove_Ops) if ((opts_ & Mut_Remove_Ops)
&& mutation_counter_-- == 0) && mutation_counter_-- == 0)
return f[0]; return f[0];
// fall through // fall through
case op::Closure: case op::Closure:
case op::NegClosure: case op::NegClosure:
case op::NegClosureMarked: case op::NegClosureMarked:
if (mutation_counter_ < 0) if (mutation_counter_ < 0)
return f; return f;
else else
return f.map(recurse); return f.map(recurse);
case op::Or: case op::Or:
case op::OrRat: case op::OrRat:
case op::And: case op::And:
case op::AndRat: case op::AndRat:
case op::AndNLM: case op::AndNLM:
case op::Concat: case op::Concat:
case op::Fusion: case op::Fusion:
{ {
int mos = f.size(); int mos = f.size();
if (opts_ & Mut_Remove_Multop_Operands) if (opts_ & Mut_Remove_Multop_Operands)
{ {
for (int i = 0; i < mos; ++i) for (int i = 0; i < mos; ++i)
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return f.all_but(i); return f.all_but(i);
} }
if (opts_ & Mut_Split_Ops && f.is(op::AndNLM)) if (opts_ & Mut_Split_Ops && f.is(op::AndNLM))
{ {
if (mutation_counter_ >= 0 if (mutation_counter_ >= 0
&& mutation_counter_ < 2 * (mos - 1)) && mutation_counter_ < 2 * (mos - 1))
{ {
vec v1; vec v1;
vec v2; vec v2;
v1.push_back(f[0]); v1.push_back(f[0]);
bool reverse = false; bool reverse = false;
int i = 1; int i = 1;
while (i < mos) while (i < mos)
{ {
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
break; break;
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
{ {
reverse = true; reverse = true;
break; break;
} }
v1.push_back(f[i++]); v1.push_back(f[i++]);
} }
for (; i < mos; ++i) for (; i < mos; ++i)
v2.push_back(f[i]); v2.push_back(f[i]);
formula first = AndNLM_(v1); formula first = AndNLM_(v1);
formula second = AndNLM_(v2); formula second = AndNLM_(v2);
formula ost = formula::one_star(); formula ost = formula::one_star();
if (!reverse) if (!reverse)
return AndRat_(Concat_(first, ost), second); return AndRat_(Concat_(first, ost), second);
else else
return AndRat_(Concat_(second, ost), first); return AndRat_(Concat_(second, ost), first);
} }
else else
{ {
mutation_counter_ -= 2 * (mos - 1); mutation_counter_ -= 2 * (mos - 1);
} }
} }
if (mutation_counter_ < 0) if (mutation_counter_ < 0)
return f; return f;
else else
return f.map(recurse); return f.map(recurse);
} }
case op::Xor: case op::Xor:
case op::Implies: case op::Implies:
case op::Equiv: case op::Equiv:
case op::U: case op::U:
case op::R: case op::R:
case op::W: case op::W:
case op::M: case op::M:
case op::EConcat: case op::EConcat:
case op::EConcatMarked: case op::EConcatMarked:
case op::UConcat: case op::UConcat:
{ {
formula first = f[0]; formula first = f[0];
formula second = f[1]; formula second = f[1];
op o = f.kind(); op o = f.kind();
bool left_is_sere = o == op::EConcat bool left_is_sere = o == op::EConcat
|| o == op::EConcatMarked || o == op::EConcatMarked
|| o == op::UConcat; || o == op::UConcat;
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0) if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
{ {
if (!left_is_sere) if (!left_is_sere)
return first; return first;
else if (o == op::UConcat) else if (o == op::UConcat)
return formula::NegClosure(first); return formula::NegClosure(first);
else // EConcat or EConcatMarked else // EConcat or EConcatMarked
return formula::Closure(first); return formula::Closure(first);
} }
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0) if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
return second; return second;
if (opts_ & Mut_Rewrite_Ops) if (opts_ & Mut_Rewrite_Ops)
{ {
switch (o) switch (o)
{ {
case op::U: case op::U:
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::W(first, second); return formula::W(first, second);
break; break;
case op::M: case op::M:
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::R(first, second); return formula::R(first, second);
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::U(second, first); return formula::U(second, first);
break; break;
case op::R: case op::R:
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::W(second, first); return formula::W(second, first);
break; break;
default: default:
break; break;
} }
} }
if (opts_ & Mut_Split_Ops) if (opts_ & Mut_Split_Ops)
{ {
switch (o) switch (o)
{ {
case op::Equiv: case op::Equiv:
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::Implies(first, second); return formula::Implies(first, second);
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::Implies(second, first); return formula::Implies(second, first);
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::And({first, second}); return formula::And({first, second});
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
{ {
// Negate the two argument sequentially (in this // Negate the two argument sequentially (in this
// case right before left, otherwise different // case right before left, otherwise different
// compilers will make different choices. // compilers will make different choices.
auto right = formula::Not(second); auto right = formula::Not(second);
return formula::And({formula::Not(first), right}); return formula::And({formula::Not(first), right});
} }
break; break;
case op::Xor: case op::Xor:
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::And({first, formula::Not(second)}); return formula::And({first, formula::Not(second)});
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::And({formula::Not(first), second}); return formula::And({formula::Not(first), second});
break; break;
default: default:
break; break;
} }
} }
if (mutation_counter_ < 0) if (mutation_counter_ < 0)
return f; return f;
else else
return f.map(recurse); return f.map(recurse);
} }
case op::Star: case op::Star:
case op::FStar: case op::FStar:
{ {
formula c = f[0]; formula c = f[0];
op o = f.kind(); op o = f.kind();
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0) if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
return c; return c;
if (opts_ & Mut_Simplify_Bounds) if (opts_ & Mut_Simplify_Bounds)
{ {
auto min = f.min(); auto min = f.min();
auto max = f.max(); auto max = f.max();
if (min > 0) if (min > 0)
{ {
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::bunop(o, c, min - 1, max); return formula::bunop(o, c, min - 1, max);
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::bunop(o, c, 0, max); return formula::bunop(o, c, 0, max);
} }
if (max != formula::unbounded()) if (max != formula::unbounded())
{ {
if (max > min && mutation_counter_-- == 0) if (max > min && mutation_counter_-- == 0)
return formula::bunop(o, c, min, max - 1); return formula::bunop(o, c, min, max - 1);
if (mutation_counter_-- == 0) if (mutation_counter_-- == 0)
return formula::bunop(o, c, min, return formula::bunop(o, c, min,
formula::unbounded()); formula::unbounded());
} }
} }
if (mutation_counter_ < 0) if (mutation_counter_ < 0)
return f; return f;
else else
return f.map(recurse); return f.map(recurse);
} }
} }
SPOT_UNREACHABLE(); SPOT_UNREACHABLE();
} }
formula formula
get_mutation(int n) get_mutation(int n)
{ {
mutation_counter_ = n; mutation_counter_ = n;
formula mut = mutate(f_); formula mut = mutate(f_);
if (mut == f_) if (mut == f_)
return nullptr; return nullptr;
return mut; return mut;
} }
}; };
@ -291,13 +291,13 @@ namespace spot
assert(left != nullptr); assert(left != nullptr);
assert(right != nullptr); assert(right != nullptr);
if (left == right) if (left == right)
return false; return false;
auto ll = length(left); auto ll = length(left);
auto lr = length(right); auto lr = length(right);
if (ll < lr) if (ll < lr)
return true; return true;
if (ll > lr) if (ll > lr)
return false; return false;
return left < right; return left < right;
} }
@ -305,55 +305,55 @@ namespace spot
void void
single_mutation_rec(formula f, fset_t& mutations, unsigned opts, single_mutation_rec(formula f, fset_t& mutations, unsigned opts,
unsigned& n, unsigned m) unsigned& n, unsigned m)
{ {
if (m == 0) if (m == 0)
{ {
if (mutations.insert(f).second) if (mutations.insert(f).second)
--n; --n;
} }
else else
{ {
formula mut; formula mut;
int i = 0; int i = 0;
mutator mv(f, opts); mutator mv(f, opts);
while (n > 0 && ((mut = mv.get_mutation(i++)) != nullptr)) while (n > 0 && ((mut = mv.get_mutation(i++)) != nullptr))
single_mutation_rec(mut, mutations, opts, n, m - 1); single_mutation_rec(mut, mutations, opts, n, m - 1);
} }
} }
void void
replace_ap_rec(formula f, fset_t& mutations, unsigned opts, replace_ap_rec(formula f, fset_t& mutations, unsigned opts,
unsigned& n, unsigned m) unsigned& n, unsigned m)
{ {
if (m == 0) if (m == 0)
{ {
if (mutations.insert(f).second) if (mutations.insert(f).second)
--n; --n;
} }
else else
{ {
if (!n) if (!n)
return; return;
auto aps = auto aps =
std::unique_ptr<atomic_prop_set>(atomic_prop_collect(f)); std::unique_ptr<atomic_prop_set>(atomic_prop_collect(f));
for (auto ap1: *aps) for (auto ap1: *aps)
for (auto ap2: *aps) for (auto ap2: *aps)
{ {
if (ap1 == ap2) if (ap1 == ap2)
continue; continue;
auto mut = substitute_ap(f, ap1, ap2); auto mut = substitute_ap(f, ap1, ap2);
replace_ap_rec(mut, mutations, opts, n, m - 1); replace_ap_rec(mut, mutations, opts, n, m - 1);
if (!n) if (!n)
return; return;
} }
} }
} }
} }
std::vector<formula> std::vector<formula>
mutate(formula f, unsigned opts, unsigned max_output, mutate(formula f, unsigned opts, unsigned max_output,
unsigned mutation_count, bool sort) unsigned mutation_count, bool sort)
{ {
fset_t mutations; fset_t mutations;
single_mutation_rec(f, mutations, opts, max_output, mutation_count); single_mutation_rec(f, mutations, opts, max_output, mutation_count);

View file

@ -38,8 +38,8 @@ namespace spot
SPOT_API SPOT_API
std::vector<formula> mutate(formula f, std::vector<formula> mutate(formula f,
unsigned opts = Mut_All, unsigned opts = Mut_All,
unsigned max_output = -1U, unsigned max_output = -1U,
unsigned mutation_count = 1, unsigned mutation_count = 1,
bool sort = true); bool sort = true);
} }

View file

@ -94,8 +94,8 @@ namespace spot
/// \param shift how many characters to add to the error locations /// \param shift how many characters to add to the error locations
/// \return \c true iff any diagnostic was output. /// \return \c true iff any diagnostic was output.
bool format_errors(std::ostream& os, bool format_errors(std::ostream& os,
const std::string& input, const std::string& input,
unsigned shift); unsigned shift);
}; };
@ -119,10 +119,10 @@ namespace spot
/// \warning This function is not reentrant. /// \warning This function is not reentrant.
SPOT_API SPOT_API
parsed_formula parse_infix_psl(const std::string& ltl_string, parsed_formula parse_infix_psl(const std::string& ltl_string,
environment& env = environment& env =
default_environment::instance(), default_environment::instance(),
bool debug = false, bool debug = false,
bool lenient = false); bool lenient = false);
/// \brief Build a Boolean formula from a string. /// \brief Build a Boolean formula from a string.
/// \param ltl_string The string to parse. /// \param ltl_string The string to parse.
@ -142,10 +142,10 @@ namespace spot
/// \warning This function is not reentrant. /// \warning This function is not reentrant.
SPOT_API SPOT_API
parsed_formula parse_infix_boolean(const std::string& ltl_string, parsed_formula parse_infix_boolean(const std::string& ltl_string,
environment& env = environment& env =
default_environment::instance(), default_environment::instance(),
bool debug = false, bool debug = false,
bool lenient = false); bool lenient = false);
/// \brief Build a formula from an LTL string in LBT's format. /// \brief Build a formula from an LTL string in LBT's format.
/// \param ltl_string The string to parse. /// \param ltl_string The string to parse.
@ -167,9 +167,9 @@ namespace spot
/// \warning This function is not reentrant. /// \warning This function is not reentrant.
SPOT_API SPOT_API
parsed_formula parse_prefix_ltl(const std::string& ltl_string, parsed_formula parse_prefix_ltl(const std::string& ltl_string,
environment& env = environment& env =
default_environment::instance(), default_environment::instance(),
bool debug = false); bool debug = false);
/// \brief A simple wrapper to parse_infix_psl() and parse_prefix_ltl(). /// \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. /// parse_infix_psl() as a parse_error exception.
SPOT_API formula SPOT_API formula
parse_formula(const std::string& ltl_string, 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. /// \brief Build a formula from a string representing a SERE.
/// \param sere_string The string to parse. /// \param sere_string The string to parse.
@ -200,10 +200,10 @@ namespace spot
/// \warning This function is not reentrant. /// \warning This function is not reentrant.
SPOT_API SPOT_API
parsed_formula parse_infix_sere(const std::string& sere_string, parsed_formula parse_infix_sere(const std::string& sere_string,
environment& env = environment& env =
default_environment::instance(), default_environment::instance(),
bool debug = false, bool debug = false,
bool lenient = false); bool lenient = false);
/// \brief Fix location of diagnostics assuming the input is utf8. /// \brief Fix location of diagnostics assuming the input is utf8.
/// ///
@ -230,7 +230,7 @@ namespace spot
SPOT_API SPOT_API
void void
fix_utf8_locations(const std::string& input_string, fix_utf8_locations(const std::string& input_string,
parse_error_list& error_list); parse_error_list& error_list);
/// @} /// @}
} }

File diff suppressed because it is too large Load diff

View file

@ -34,14 +34,14 @@ namespace spot
/// \param os The stream where it should be output. /// \param os The stream where it should be output.
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::ostream& SPOT_API std::ostream&
print_psl(std::ostream& os, formula f, bool full_parent = false); print_psl(std::ostream& os, formula f, bool full_parent = false);
/// \brief Convert a PSL formula into a string which is parsable /// \brief Convert a PSL formula into a string which is parsable
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::string SPOT_API std::string
str_psl(formula f, bool full_parent = false); str_psl(formula f, bool full_parent = false);
@ -49,15 +49,15 @@ namespace spot
/// \param os The stream where it should be output. /// \param os The stream where it should be output.
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::ostream& SPOT_API std::ostream&
print_utf8_psl(std::ostream& os, formula f, 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 /// \brief Convert a PSL formula into a utf-8 string which is parsable
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::string SPOT_API std::string
str_utf8_psl(formula f, bool full_parent = false); str_utf8_psl(formula f, bool full_parent = false);
@ -65,14 +65,14 @@ namespace spot
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param os The stream where it should be output. /// \param os The stream where it should be output.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::ostream& SPOT_API std::ostream&
print_sere(std::ostream& os, formula f, bool full_parent = false); print_sere(std::ostream& os, formula f, bool full_parent = false);
/// \brief Convert a SERE formula into a string which is parsable /// \brief Convert a SERE formula into a string which is parsable
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::string SPOT_API std::string
str_sere(formula f, bool full_parent = false); str_sere(formula f, bool full_parent = false);
@ -80,15 +80,15 @@ namespace spot
/// \param os The stream where it should be output. /// \param os The stream where it should be output.
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::ostream& SPOT_API std::ostream&
print_utf8_sere(std::ostream& os, formula f, 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 /// \brief Convert a SERE formula into a string which is parsable
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::string SPOT_API std::string
str_utf8_sere(formula f, bool full_parent = false); 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 os The stream where it should be output.
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::ostream& SPOT_API std::ostream&
print_spin_ltl(std::ostream& os, formula f, 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. /// \brief Convert an LTL formula into a string parsable by Spin.
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::string SPOT_API std::string
str_spin_ltl(formula f, bool full_parent = false); 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 os The stream where it should be output.
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::ostream& SPOT_API std::ostream&
print_latex_psl(std::ostream& os, formula f, 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. /// \brief Output a formula as a LaTeX string which is parsable.
/// unless the formula contains automaton operators (used in ELTL formulae). /// unless the formula contains automaton operators (used in ELTL formulae).
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::string SPOT_API std::string
str_latex_psl(formula f, bool full_parent = false); 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 os The stream where it should be output.
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::ostream& SPOT_API std::ostream&
print_latex_sere(std::ostream& os, formula f, 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. /// \brief Output a SERE formula as a LaTeX string which is parsable.
/// unless the formula contains automaton operators (used in ELTL formulae). /// unless the formula contains automaton operators (used in ELTL formulae).
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::string SPOT_API std::string
str_latex_sere(formula f, bool full_parent = false); 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 os The stream where it should be output.
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::ostream& SPOT_API std::ostream&
print_sclatex_psl(std::ostream& os, formula f, 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. /// \brief Output a PSL formula as a self-contained LaTeX string.
/// ///
/// The result cannot be parsed bacl. /// The result cannot be parsed bacl.
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::string SPOT_API std::string
str_sclatex_psl(formula f, bool full_parent = false); 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 os The stream where it should be output.
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::ostream& SPOT_API std::ostream&
print_sclatex_sere(std::ostream& os, formula f, 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. /// \brief Output a SERE formula as a self-contained LaTeX string.
/// ///
/// The result cannot be parsed bacl. /// The result cannot be parsed bacl.
/// \param f The formula to translate. /// \param f The formula to translate.
/// \param full_parent Whether or not the string should by fully /// \param full_parent Whether or not the string should by fully
/// parenthesized. /// parenthesized.
SPOT_API std::string SPOT_API std::string
str_sclatex_sere(formula f, bool full_parent = false); str_sclatex_sere(formula f, bool full_parent = false);

View file

@ -183,24 +183,24 @@ namespace spot
total_2_and_more_ = 0.0; total_2_and_more_ = 0.0;
for (unsigned i = 0; i < proba_size_; ++i) for (unsigned i = 0; i < proba_size_; ++i)
{ {
if (proba_[i].min_n == 1) if (proba_[i].min_n == 1)
{ {
total_1_ += proba_[i].proba; total_1_ += proba_[i].proba;
if (proba_ + i >= proba_2_) if (proba_ + i >= proba_2_)
total_2_ += proba_[i].proba; total_2_ += proba_[i].proba;
if (proba_ + i >= proba_2_or_more_) if (proba_ + i >= proba_2_or_more_)
total_2_and_more_ += proba_[i].proba; total_2_and_more_ += proba_[i].proba;
} }
else if (proba_[i].min_n == 2) else if (proba_[i].min_n == 2)
{ {
total_2_ += proba_[i].proba; total_2_ += proba_[i].proba;
if (proba_ + i >= proba_2_or_more_) if (proba_ + i >= proba_2_or_more_)
total_2_and_more_ += proba_[i].proba; total_2_and_more_ += proba_[i].proba;
} }
else if (proba_[i].min_n > 2) else if (proba_[i].min_n > 2)
total_2_and_more_ += proba_[i].proba; total_2_and_more_ += proba_[i].proba;
else else
SPOT_UNREACHABLE(); // unexpected max_n SPOT_UNREACHABLE(); // unexpected max_n
} }
assert(total_2_and_more_ >= total_2_); assert(total_2_and_more_ >= total_2_);
} }
@ -216,48 +216,48 @@ namespace spot
// Approximate impossible cases. // Approximate impossible cases.
if (n == 1 && total_1_ == 0.0) if (n == 1 && total_1_ == 0.0)
{ {
if (total_2_ != 0.0) if (total_2_ != 0.0)
n = 2; n = 2;
else else
n = 3; n = 3;
} }
else if (n == 2 && total_2_ == 0.0) else if (n == 2 && total_2_ == 0.0)
{ {
if (total_1_ != 0.0) if (total_1_ != 0.0)
n = 1; n = 1;
else else
n = 3; n = 3;
} }
else if (n > 2 && total_2_and_more_ == 0.0) else if (n > 2 && total_2_and_more_ == 0.0)
{ {
if (total_1_ != 0.0) if (total_1_ != 0.0)
n = 1; n = 1;
else else
assert(total_2_ == 0.0); assert(total_2_ == 0.0);
} }
if (n == 1) if (n == 1)
{ {
r *= total_1_; r *= total_1_;
p = proba_; p = proba_;
} }
else if (n == 2) else if (n == 2)
{ {
r *= total_2_; r *= total_2_;
p = proba_2_; p = proba_2_;
} }
else else
{ {
r *= total_2_and_more_; r *= total_2_and_more_;
p = proba_2_or_more_; p = proba_2_or_more_;
} }
double s = p->proba; double s = p->proba;
while (s < r) while (s < r)
{ {
++p; ++p;
s += p->proba; s += p->proba;
} }
return p->build(this, n); return p->build(this, n);
@ -271,30 +271,30 @@ namespace spot
char* key = strtok(options, "=\t, :;"); char* key = strtok(options, "=\t, :;");
while (key) while (key)
{ {
char* value = strtok(nullptr, "=\t, :;"); char* value = strtok(nullptr, "=\t, :;");
if (!value) if (!value)
return key; return key;
char* endptr; char* endptr;
double res = strtod(value, &endptr); double res = strtod(value, &endptr);
if (*endptr) if (*endptr)
return value; return value;
unsigned i; unsigned i;
for (i = 0; i < proba_size_; ++i) for (i = 0; i < proba_size_; ++i)
{ {
if (('a' <= *proba_[i].name && *proba_[i].name <= 'z' if (('a' <= *proba_[i].name && *proba_[i].name <= 'z'
&& !strcasecmp(proba_[i].name, key)) && !strcasecmp(proba_[i].name, key))
|| !strcmp(proba_[i].name, key)) || !strcmp(proba_[i].name, key))
{ {
proba_[i].proba = res; proba_[i].proba = res;
break; break;
} }
} }
if (i == proba_size_) if (i == proba_size_)
return key; return key;
key = strtok(nullptr, "=\t, :;"); key = strtok(nullptr, "=\t, :;");
} }
update_sums(); update_sums();
return nullptr; return nullptr;
@ -393,7 +393,7 @@ namespace spot
{ {
// FIXME: This looks very fragile. // FIXME: This looks very fragile.
memmove(proba_ + 8, proba_ + 7, 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_[7].setup("Closure", 2, closure_builder);
proba_[17].setup("EConcat", 3, binop_SERELTL_builder<op::EConcat>); proba_[17].setup("EConcat", 3, binop_SERELTL_builder<op::EConcat>);
@ -402,10 +402,10 @@ namespace spot
} }
randltlgenerator::randltlgenerator(atomic_prop_set aprops, randltlgenerator::randltlgenerator(atomic_prop_set aprops,
const option_map& opts, const option_map& opts,
char* opt_pL, char* opt_pL,
char* opt_pS, char* opt_pS,
char* opt_pB) char* opt_pB)
{ {
aprops_ = aprops; aprops_ = aprops;
output_ = opts.get("output", OUTPUTLTL); output_ = opts.get("output", OUTPUTLTL);
@ -423,51 +423,51 @@ namespace spot
switch (output_) switch (output_)
{ {
case OUTPUTLTL: case OUTPUTLTL:
rf_ = new random_ltl(&aprops_); rf_ = new random_ltl(&aprops_);
if (opt_pS) if (opt_pS)
throw std::invalid_argument("Cannot set sere priorities with " throw std::invalid_argument("Cannot set sere priorities with "
"LTL output"); "LTL output");
if (opt_pB) if (opt_pB)
throw std::invalid_argument("Cannot set boolean priorities with " throw std::invalid_argument("Cannot set boolean priorities with "
"LTL output"); "LTL output");
tok_pL = rf_->parse_options(opt_pL); tok_pL = rf_->parse_options(opt_pL);
break; break;
case OUTPUTBOOL: case OUTPUTBOOL:
rf_ = new random_boolean(&aprops_); rf_ = new random_boolean(&aprops_);
tok_pB = rf_->parse_options(opt_pB); tok_pB = rf_->parse_options(opt_pB);
if (opt_pL) if (opt_pL)
throw std::invalid_argument("Cannot set ltl priorities with " throw std::invalid_argument("Cannot set ltl priorities with "
"Boolean output"); "Boolean output");
if (opt_pS) if (opt_pS)
throw std::invalid_argument("Cannot set sere priorities " throw std::invalid_argument("Cannot set sere priorities "
"with Boolean output"); "with Boolean output");
break; break;
case OUTPUTSERE: case OUTPUTSERE:
rf_ = rs_ = new random_sere(&aprops_); rf_ = rs_ = new random_sere(&aprops_);
tok_pS = rs_->parse_options(opt_pS); tok_pS = rs_->parse_options(opt_pS);
tok_pB = rs_->rb.parse_options(opt_pB); tok_pB = rs_->rb.parse_options(opt_pB);
if (opt_pL) if (opt_pL)
throw std::invalid_argument("Cannot set ltl priorities " throw std::invalid_argument("Cannot set ltl priorities "
"with SERE output"); "with SERE output");
break; break;
case OUTPUTPSL: case OUTPUTPSL:
rf_ = rp_ = new random_psl(&aprops_); rf_ = rp_ = new random_psl(&aprops_);
rs_ = &rp_->rs; rs_ = &rp_->rs;
tok_pL = rp_->parse_options(opt_pL); tok_pL = rp_->parse_options(opt_pL);
tok_pS = rs_->parse_options(opt_pS); tok_pS = rs_->parse_options(opt_pS);
tok_pB = rs_->rb.parse_options(opt_pB); tok_pB = rs_->rb.parse_options(opt_pB);
break; break;
} }
if (tok_pL) if (tok_pL)
throw std::invalid_argument("failed to parse LTL priorities near " throw std::invalid_argument("failed to parse LTL priorities near "
+ std::string(tok_pL)); + std::string(tok_pL));
if (tok_pS) if (tok_pS)
throw std::invalid_argument("failed to parse SERE priorities near " throw std::invalid_argument("failed to parse SERE priorities near "
+ std::string(tok_pS)); + std::string(tok_pS));
if (tok_pB) if (tok_pB)
throw std::invalid_argument("failed to parse Boolean priorities near " throw std::invalid_argument("failed to parse Boolean priorities near "
+ std::string(tok_pB)); + std::string(tok_pB));
spot::srand(opt_seed_); spot::srand(opt_seed_);
tl_simplifier_options simpl_opts(opt_simpl_level_); tl_simplifier_options simpl_opts(opt_simpl_level_);
@ -475,12 +475,12 @@ namespace spot
} }
randltlgenerator::randltlgenerator(int aprops_n, randltlgenerator::randltlgenerator(int aprops_n,
const option_map& opts, const option_map& opts,
char* opt_pL, char* opt_pL,
char* opt_pS, char* opt_pS,
char* opt_pB) char* opt_pB)
: randltlgenerator(create_atomic_prop_set(aprops_n), opts, : 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; formula f = nullptr;
do do
{ {
ignore = false; ignore = false;
int size = opt_tree_size_min_; int size = opt_tree_size_min_;
if (size != opt_tree_size_max_) if (size != opt_tree_size_max_)
size = spot::rrand(size, opt_tree_size_max_); size = spot::rrand(size, opt_tree_size_max_);
f = rf_->generate(size); f = rf_->generate(size);
if (opt_wf_) if (opt_wf_)
{ {
atomic_prop_set s = aprops_; atomic_prop_set s = aprops_;
remove_some_props(s); remove_some_props(s);
f = formula::And({f, GF_n()}); f = formula::And({f, GF_n()});
} }
if (opt_simpl_level_) if (opt_simpl_level_)
f = simpl_.simplify(f); f = simpl_.simplify(f);
if (opt_unique_ && !unique_set_.insert(f).second) if (opt_unique_ && !unique_set_.insert(f).second)
ignore = true; ignore = true;
} while (ignore && --trials); } while (ignore && --trials);
if (trials <= 0) if (trials <= 0)
return nullptr; return nullptr;
@ -529,9 +529,9 @@ namespace spot
while (n--) while (n--)
{ {
auto i = s.begin(); auto i = s.begin();
std::advance(i, spot::mrand(s.size())); std::advance(i, spot::mrand(s.size()));
s.erase(i); s.erase(i);
} }
} }
@ -542,11 +542,11 @@ namespace spot
formula res = nullptr; formula res = nullptr;
for (auto v: aprops_) for (auto v: aprops_)
{ {
formula f = formula::G(formula::F(v)); formula f = formula::G(formula::F(v));
if (res) if (res)
res = formula::And({f, res}); res = formula::And({f, res});
else else
res = f; res = f;
} }
return res; return res;
} }

Some files were not shown because too many files have changed in this diff Show more