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:
parent
1eee12b8b4
commit
f7e7b4f14e
239 changed files with 25359 additions and 25355 deletions
342
bin/autfilt.cc
342
bin/autfilt.cc
|
|
@ -363,9 +363,9 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case 'x':
|
||||
{
|
||||
const char* opt = extra_options.parse_options(arg);
|
||||
if (opt)
|
||||
error(2, 0, "failed to parse --options near '%s'", opt);
|
||||
const char* opt = extra_options.parse_options(arg);
|
||||
if (opt)
|
||||
error(2, 0, "failed to parse --options near '%s'", opt);
|
||||
}
|
||||
break;
|
||||
case OPT_AP_N:
|
||||
|
|
@ -376,15 +376,15 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case OPT_ACCEPT_WORD:
|
||||
try
|
||||
{
|
||||
opt->acc_words.push_back(spot::parse_word(arg, opt->dict)
|
||||
->as_automaton());
|
||||
}
|
||||
{
|
||||
opt->acc_words.push_back(spot::parse_word(arg, opt->dict)
|
||||
->as_automaton());
|
||||
}
|
||||
catch (const spot::parse_error& e)
|
||||
{
|
||||
error(2, 0, "failed to parse the argument of --accept-word:\n%s",
|
||||
e.what());
|
||||
}
|
||||
{
|
||||
error(2, 0, "failed to parse the argument of --accept-word:\n%s",
|
||||
e.what());
|
||||
}
|
||||
break;
|
||||
case OPT_ARE_ISOMORPHIC:
|
||||
opt->are_isomorphic = read_automaton(arg, opt->dict);
|
||||
|
|
@ -420,27 +420,27 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case OPT_EQUIVALENT_TO:
|
||||
if (opt->equivalent_pos)
|
||||
error(2, 0, "only one --equivalent-to option can be given");
|
||||
error(2, 0, "only one --equivalent-to option can be given");
|
||||
opt->equivalent_pos = read_automaton(arg, opt->dict);
|
||||
opt->equivalent_neg =
|
||||
spot::dtwa_complement(ensure_deterministic(opt->equivalent_pos));
|
||||
spot::dtwa_complement(ensure_deterministic(opt->equivalent_pos));
|
||||
break;
|
||||
case OPT_INSTUT:
|
||||
if (!arg || (arg[0] == '1' && arg[1] == 0))
|
||||
opt_instut = 1;
|
||||
opt_instut = 1;
|
||||
else if (arg[0] == '2' && arg[1] == 0)
|
||||
opt_instut = 2;
|
||||
opt_instut = 2;
|
||||
else
|
||||
error(2, 0, "unknown argument for --instut: %s", arg);
|
||||
error(2, 0, "unknown argument for --instut: %s", arg);
|
||||
break;
|
||||
case OPT_INCLUDED_IN:
|
||||
{
|
||||
auto aut = ensure_deterministic(read_automaton(arg, opt->dict));
|
||||
aut = spot::dtwa_complement(aut);
|
||||
if (!opt->included_in)
|
||||
opt->included_in = aut;
|
||||
else
|
||||
opt->included_in = spot::product_or(opt->included_in, aut);
|
||||
auto aut = ensure_deterministic(read_automaton(arg, opt->dict));
|
||||
aut = spot::dtwa_complement(aut);
|
||||
if (!opt->included_in)
|
||||
opt->included_in = aut;
|
||||
else
|
||||
opt->included_in = spot::product_or(opt->included_in, aut);
|
||||
}
|
||||
break;
|
||||
case OPT_INTERSECT:
|
||||
|
|
@ -472,18 +472,18 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case OPT_MASK_ACC:
|
||||
{
|
||||
for (auto res : to_longs(arg))
|
||||
{
|
||||
if (res < 0)
|
||||
error(2, 0, "acceptance sets should be non-negative:"
|
||||
" --mask-acc=%ld", res);
|
||||
if (static_cast<unsigned long>(res)
|
||||
> sizeof(spot::acc_cond::mark_t::value_t))
|
||||
error(2, 0, "this implementation does not support that many"
|
||||
" acceptance sets: --mask-acc=%ld", res);
|
||||
opt_mask_acc.set(res);
|
||||
}
|
||||
break;
|
||||
for (auto res : to_longs(arg))
|
||||
{
|
||||
if (res < 0)
|
||||
error(2, 0, "acceptance sets should be non-negative:"
|
||||
" --mask-acc=%ld", res);
|
||||
if (static_cast<unsigned long>(res)
|
||||
> sizeof(spot::acc_cond::mark_t::value_t))
|
||||
error(2, 0, "this implementation does not support that many"
|
||||
" acceptance sets: --mask-acc=%ld", res);
|
||||
opt_mask_acc.set(res);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OPT_KEEP_STATES:
|
||||
{
|
||||
|
|
@ -491,71 +491,71 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
if (!values.empty())
|
||||
opt_keep_states_initial = values[0];
|
||||
for (auto res : values)
|
||||
{
|
||||
if (res < 0)
|
||||
error(2, 0, "state ids should be non-negative:"
|
||||
" --mask-acc=%ld", res);
|
||||
{
|
||||
if (res < 0)
|
||||
error(2, 0, "state ids should be non-negative:"
|
||||
" --mask-acc=%ld", res);
|
||||
// We don't know yet how many states the automata contain.
|
||||
if (opt_keep_states.size() <= static_cast<unsigned long>(res))
|
||||
opt_keep_states.resize(res + 1, false);
|
||||
opt_keep_states[res] = true;
|
||||
}
|
||||
opt_rem_unreach = true;
|
||||
break;
|
||||
opt_keep_states[res] = true;
|
||||
}
|
||||
opt_rem_unreach = true;
|
||||
break;
|
||||
}
|
||||
case OPT_PRODUCT_AND:
|
||||
{
|
||||
auto a = read_automaton(arg, opt->dict);
|
||||
if (!opt->product_and)
|
||||
opt->product_and = std::move(a);
|
||||
else
|
||||
opt->product_and = spot::product(std::move(opt->product_and),
|
||||
std::move(a));
|
||||
auto a = read_automaton(arg, opt->dict);
|
||||
if (!opt->product_and)
|
||||
opt->product_and = std::move(a);
|
||||
else
|
||||
opt->product_and = spot::product(std::move(opt->product_and),
|
||||
std::move(a));
|
||||
}
|
||||
break;
|
||||
case OPT_PRODUCT_OR:
|
||||
{
|
||||
auto a = read_automaton(arg, opt->dict);
|
||||
if (!opt->product_or)
|
||||
opt->product_or = std::move(a);
|
||||
else
|
||||
opt->product_or = spot::product_or(std::move(opt->product_or),
|
||||
std::move(a));
|
||||
auto a = read_automaton(arg, opt->dict);
|
||||
if (!opt->product_or)
|
||||
opt->product_or = std::move(a);
|
||||
else
|
||||
opt->product_or = spot::product_or(std::move(opt->product_or),
|
||||
std::move(a));
|
||||
}
|
||||
break;
|
||||
case OPT_RANDOMIZE:
|
||||
if (arg)
|
||||
{
|
||||
for (auto p = arg; *p; ++p)
|
||||
switch (*p)
|
||||
{
|
||||
case 's':
|
||||
randomize_st = true;
|
||||
break;
|
||||
case 't':
|
||||
randomize_tr = true;
|
||||
break;
|
||||
default:
|
||||
error(2, 0, "unknown argument for --randomize: '%c'", *p);
|
||||
}
|
||||
}
|
||||
{
|
||||
for (auto p = arg; *p; ++p)
|
||||
switch (*p)
|
||||
{
|
||||
case 's':
|
||||
randomize_st = true;
|
||||
break;
|
||||
case 't':
|
||||
randomize_tr = true;
|
||||
break;
|
||||
default:
|
||||
error(2, 0, "unknown argument for --randomize: '%c'", *p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
randomize_tr = true;
|
||||
randomize_st = true;
|
||||
}
|
||||
{
|
||||
randomize_tr = true;
|
||||
randomize_st = true;
|
||||
}
|
||||
break;
|
||||
case OPT_REJECT_WORD:
|
||||
try
|
||||
{
|
||||
opt->rej_words.push_back(spot::parse_word(arg, opt->dict)
|
||||
->as_automaton());
|
||||
}
|
||||
{
|
||||
opt->rej_words.push_back(spot::parse_word(arg, opt->dict)
|
||||
->as_automaton());
|
||||
}
|
||||
catch (const spot::parse_error& e)
|
||||
{
|
||||
error(2, 0, "failed to parse the argument of --reject-word:\n%s",
|
||||
e.what());
|
||||
}
|
||||
{
|
||||
error(2, 0, "failed to parse the argument of --reject-word:\n%s",
|
||||
e.what());
|
||||
}
|
||||
break;
|
||||
case OPT_REM_AP:
|
||||
opt->rem_ap.add_ap(arg);
|
||||
|
|
@ -621,7 +621,7 @@ namespace
|
|||
|
||||
int
|
||||
process_automaton(const spot::const_parsed_aut_ptr& haut,
|
||||
const char* filename)
|
||||
const char* filename)
|
||||
{
|
||||
spot::stopwatch sw;
|
||||
sw.start();
|
||||
|
|
@ -630,30 +630,30 @@ namespace
|
|||
// never modify the original automaton (e.g. with
|
||||
// merge_edges()) and the statistics about it make sense.
|
||||
auto aut = ((automaton_format == Stats) || opt_name)
|
||||
? spot::make_twa_graph(haut->aut, spot::twa::prop_set::all())
|
||||
: haut->aut;
|
||||
? spot::make_twa_graph(haut->aut, spot::twa::prop_set::all())
|
||||
: haut->aut;
|
||||
|
||||
// Preprocessing.
|
||||
|
||||
if (opt_stripacc)
|
||||
spot::strip_acceptance_here(aut);
|
||||
spot::strip_acceptance_here(aut);
|
||||
if (opt_merge)
|
||||
aut->merge_edges();
|
||||
aut->merge_edges();
|
||||
if (opt_clean_acc || opt_rem_fin)
|
||||
cleanup_acceptance_here(aut);
|
||||
cleanup_acceptance_here(aut);
|
||||
if (opt_sep_sets)
|
||||
separate_sets_here(aut);
|
||||
separate_sets_here(aut);
|
||||
if (opt_complement_acc)
|
||||
aut->set_acceptance(aut->acc().num_sets(),
|
||||
aut->get_acceptance().complement());
|
||||
aut->set_acceptance(aut->acc().num_sets(),
|
||||
aut->get_acceptance().complement());
|
||||
if (opt_rem_fin)
|
||||
aut = remove_fin(aut);
|
||||
aut = remove_fin(aut);
|
||||
if (opt_dnf_acc)
|
||||
aut->set_acceptance(aut->acc().num_sets(),
|
||||
aut->get_acceptance().to_dnf());
|
||||
aut->set_acceptance(aut->acc().num_sets(),
|
||||
aut->get_acceptance().to_dnf());
|
||||
if (opt_cnf_acc)
|
||||
aut->set_acceptance(aut->acc().num_sets(),
|
||||
aut->get_acceptance().to_cnf());
|
||||
aut->set_acceptance(aut->acc().num_sets(),
|
||||
aut->get_acceptance().to_cnf());
|
||||
|
||||
// Filters.
|
||||
|
||||
|
|
@ -664,46 +664,46 @@ namespace
|
|||
matched &= opt_accsets.contains(aut->acc().num_sets());
|
||||
matched &= opt_ap_n.contains(aut->ap().size());
|
||||
if (opt_is_complete)
|
||||
matched &= is_complete(aut);
|
||||
matched &= is_complete(aut);
|
||||
if (opt_is_deterministic)
|
||||
matched &= is_deterministic(aut);
|
||||
matched &= is_deterministic(aut);
|
||||
if (opt_is_deterministic)
|
||||
matched &= is_deterministic(aut);
|
||||
matched &= is_deterministic(aut);
|
||||
else if (opt_is_unambiguous)
|
||||
matched &= is_unambiguous(aut);
|
||||
matched &= is_unambiguous(aut);
|
||||
if (opt_is_terminal)
|
||||
matched &= is_terminal_automaton(aut);
|
||||
matched &= is_terminal_automaton(aut);
|
||||
else if (opt_is_weak)
|
||||
matched &= is_weak_automaton(aut);
|
||||
matched &= is_weak_automaton(aut);
|
||||
else if (opt_is_inherently_weak)
|
||||
matched &= is_inherently_weak_automaton(aut);
|
||||
matched &= is_inherently_weak_automaton(aut);
|
||||
if (opt->are_isomorphic)
|
||||
matched &= opt->isomorphism_checker->is_isomorphic(aut);
|
||||
if (opt_is_empty)
|
||||
matched &= aut->is_empty();
|
||||
matched &= aut->is_empty();
|
||||
if (opt->intersect)
|
||||
matched &= !spot::product(aut, opt->intersect)->is_empty();
|
||||
matched &= !spot::product(aut, opt->intersect)->is_empty();
|
||||
if (opt->included_in)
|
||||
matched &= spot::product(aut, opt->included_in)->is_empty();
|
||||
matched &= spot::product(aut, opt->included_in)->is_empty();
|
||||
if (opt->equivalent_pos)
|
||||
matched &= spot::product(aut, opt->equivalent_neg)->is_empty()
|
||||
&& spot::product(dtwa_complement(ensure_deterministic(aut)),
|
||||
opt->equivalent_pos)->is_empty();
|
||||
matched &= spot::product(aut, opt->equivalent_neg)->is_empty()
|
||||
&& spot::product(dtwa_complement(ensure_deterministic(aut)),
|
||||
opt->equivalent_pos)->is_empty();
|
||||
|
||||
if (matched && !opt->acc_words.empty())
|
||||
for (auto& word_aut: opt->acc_words)
|
||||
if (spot::product(aut, word_aut)->is_empty())
|
||||
{
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
for (auto& word_aut: opt->acc_words)
|
||||
if (spot::product(aut, word_aut)->is_empty())
|
||||
{
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
if (matched && !opt->rej_words.empty())
|
||||
for (auto& word_aut: opt->rej_words)
|
||||
if (!spot::product(aut, word_aut)->is_empty())
|
||||
{
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
for (auto& word_aut: opt->rej_words)
|
||||
if (!spot::product(aut, word_aut)->is_empty())
|
||||
{
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Drop or keep matched automata depending on the --invert option
|
||||
if (matched == opt_invert)
|
||||
|
|
@ -712,65 +712,65 @@ namespace
|
|||
// Postprocessing.
|
||||
|
||||
if (opt_mask_acc)
|
||||
aut = mask_acc_sets(aut, opt_mask_acc & aut->acc().all_sets());
|
||||
aut = mask_acc_sets(aut, opt_mask_acc & aut->acc().all_sets());
|
||||
|
||||
if (!opt->excl_ap.empty())
|
||||
aut = opt->excl_ap.constrain(aut, opt_simplify_exclusive_ap);
|
||||
aut = opt->excl_ap.constrain(aut, opt_simplify_exclusive_ap);
|
||||
|
||||
if (!opt->rem_ap.empty())
|
||||
aut = opt->rem_ap.strip(aut);
|
||||
aut = opt->rem_ap.strip(aut);
|
||||
|
||||
if (opt_destut)
|
||||
aut = spot::closure(std::move(aut));
|
||||
aut = spot::closure(std::move(aut));
|
||||
if (opt_instut == 1)
|
||||
aut = spot::sl(std::move(aut));
|
||||
aut = spot::sl(std::move(aut));
|
||||
else if (opt_instut == 2)
|
||||
aut = spot::sl2(std::move(aut));
|
||||
aut = spot::sl2(std::move(aut));
|
||||
|
||||
if (!opt_keep_states.empty())
|
||||
aut = mask_keep_states(aut, opt_keep_states, opt_keep_states_initial);
|
||||
aut = mask_keep_states(aut, opt_keep_states, opt_keep_states_initial);
|
||||
if (opt_rem_dead)
|
||||
aut->purge_dead_states();
|
||||
aut->purge_dead_states();
|
||||
else if (opt_rem_unreach)
|
||||
aut->purge_unreachable_states();
|
||||
aut->purge_unreachable_states();
|
||||
|
||||
if (opt->product_and)
|
||||
aut = spot::product(std::move(aut), opt->product_and);
|
||||
aut = spot::product(std::move(aut), opt->product_and);
|
||||
if (opt->product_or)
|
||||
aut = spot::product_or(std::move(aut), opt->product_or);
|
||||
aut = spot::product_or(std::move(aut), opt->product_or);
|
||||
|
||||
if (opt_decompose_strength)
|
||||
{
|
||||
aut = decompose_strength(aut, opt_decompose_strength);
|
||||
if (!aut)
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
aut = decompose_strength(aut, opt_decompose_strength);
|
||||
if (!aut)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opt_sat_minimize)
|
||||
{
|
||||
aut = spot::sat_minimize(aut, opt_sat_minimize, sbacc);
|
||||
if (!aut)
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
aut = spot::sat_minimize(aut, opt_sat_minimize, sbacc);
|
||||
if (!aut)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opt_complement)
|
||||
aut = spot::dtwa_complement(ensure_deterministic(aut));
|
||||
aut = spot::dtwa_complement(ensure_deterministic(aut));
|
||||
|
||||
aut = post.run(aut, nullptr);
|
||||
|
||||
if (randomize_st || randomize_tr)
|
||||
spot::randomize(aut, randomize_st, randomize_tr);
|
||||
spot::randomize(aut, randomize_st, randomize_tr);
|
||||
|
||||
const double conversion_time = sw.stop();
|
||||
|
||||
if (opt->uniq)
|
||||
{
|
||||
auto tmp =
|
||||
spot::canonicalize(make_twa_graph(aut,
|
||||
spot::twa::prop_set::all()));
|
||||
spot::canonicalize(make_twa_graph(aut,
|
||||
spot::twa::prop_set::all()));
|
||||
if (!opt->uniq->emplace(tmp->edge_vector().begin() + 1,
|
||||
tmp->edge_vector().end()).second)
|
||||
return 0;
|
||||
tmp->edge_vector().end()).second)
|
||||
return 0;
|
||||
}
|
||||
|
||||
++match_count;
|
||||
|
|
@ -778,7 +778,7 @@ namespace
|
|||
printer.print(aut, nullptr, filename, -1, conversion_time, haut);
|
||||
|
||||
if (opt_max_count >= 0 && match_count >= opt_max_count)
|
||||
abort_run = true;
|
||||
abort_run = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -796,19 +796,19 @@ namespace
|
|||
auto hp = spot::automaton_stream_parser(filename, opt_parse);
|
||||
int err = 0;
|
||||
while (!abort_run)
|
||||
{
|
||||
auto haut = hp.parse(opt->dict);
|
||||
if (!haut->aut && haut->errors.empty())
|
||||
break;
|
||||
if (haut->format_errors(std::cerr))
|
||||
err = 2;
|
||||
if (!haut->aut)
|
||||
error(2, 0, "failed to read automaton from %s", filename);
|
||||
else if (haut->aborted)
|
||||
err = std::max(err, aborted(haut, filename));
|
||||
else
|
||||
{
|
||||
auto haut = hp.parse(opt->dict);
|
||||
if (!haut->aut && haut->errors.empty())
|
||||
break;
|
||||
if (haut->format_errors(std::cerr))
|
||||
err = 2;
|
||||
if (!haut->aut)
|
||||
error(2, 0, "failed to read automaton from %s", filename);
|
||||
else if (haut->aborted)
|
||||
err = std::max(err, aborted(haut, filename));
|
||||
else
|
||||
process_automaton(haut, filename);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
};
|
||||
|
|
@ -820,7 +820,7 @@ main(int argc, char** argv)
|
|||
setup(argv);
|
||||
|
||||
const argp ap = { options, parse_opt, "[FILENAMES...]",
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -834,23 +834,23 @@ main(int argc, char** argv)
|
|||
pref = spot::postprocessor::Any;
|
||||
type = spot::postprocessor::Generic;
|
||||
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
|
||||
exit(err);
|
||||
exit(err);
|
||||
|
||||
if (level_set && !pref_set)
|
||||
pref = spot::postprocessor::Small;
|
||||
pref = spot::postprocessor::Small;
|
||||
if (pref_set && !level_set)
|
||||
level = spot::postprocessor::High;
|
||||
level = spot::postprocessor::High;
|
||||
|
||||
if (jobs.empty())
|
||||
jobs.emplace_back("-", true);
|
||||
jobs.emplace_back("-", true);
|
||||
|
||||
if (opt->are_isomorphic)
|
||||
{
|
||||
if (opt_merge)
|
||||
opt->are_isomorphic->merge_edges();
|
||||
opt->isomorphism_checker = std::unique_ptr<spot::isomorphism_checker>
|
||||
(new spot::isomorphism_checker(opt->are_isomorphic));
|
||||
}
|
||||
{
|
||||
if (opt_merge)
|
||||
opt->are_isomorphic->merge_edges();
|
||||
opt->isomorphism_checker = std::unique_ptr<spot::isomorphism_checker>
|
||||
(new spot::isomorphism_checker(opt->are_isomorphic));
|
||||
}
|
||||
|
||||
|
||||
spot::srand(opt_seed);
|
||||
|
|
@ -862,7 +862,7 @@ main(int argc, char** argv)
|
|||
|
||||
hoa_processor processor(post);
|
||||
if (processor.run())
|
||||
return 2;
|
||||
return 2;
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ static const argp_option options[] =
|
|||
};
|
||||
|
||||
const struct argp aoutput_argp = { options, parse_opt_aoutput, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr };
|
||||
nullptr, nullptr, nullptr };
|
||||
|
||||
// Those can be overridden by individual tools. E.g. randaut has no
|
||||
// notion of input file, so %F and %L represent something else.
|
||||
|
|
@ -181,8 +181,8 @@ static const argp_option io_options[] =
|
|||
};
|
||||
|
||||
const struct argp aoutput_io_format_argp = { io_options, nullptr, nullptr,
|
||||
nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
|
||||
static const argp_option o_options[] =
|
||||
{
|
||||
|
|
@ -221,8 +221,8 @@ static const argp_option o_options[] =
|
|||
};
|
||||
|
||||
const struct argp aoutput_o_format_argp = { o_options,
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr };
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr };
|
||||
|
||||
int parse_opt_aoutput(int key, char* arg, struct argp_state*)
|
||||
{
|
||||
|
|
@ -249,15 +249,15 @@ int parse_opt_aoutput(int key, char* arg, struct argp_state*)
|
|||
case 's':
|
||||
automaton_format = Spin;
|
||||
if (type != spot::postprocessor::Monitor)
|
||||
type = spot::postprocessor::BA;
|
||||
type = spot::postprocessor::BA;
|
||||
automaton_format_opt = arg;
|
||||
break;
|
||||
case OPT_CHECK:
|
||||
automaton_format = Hoa;
|
||||
if (arg)
|
||||
opt_check |= XARGMATCH("--check", arg, check_args, check_types);
|
||||
opt_check |= XARGMATCH("--check", arg, check_args, check_types);
|
||||
else
|
||||
opt_check |= check_all;
|
||||
opt_check |= check_all;
|
||||
break;
|
||||
case OPT_LBTT:
|
||||
automaton_format = Lbtt;
|
||||
|
|
@ -266,14 +266,14 @@ int parse_opt_aoutput(int key, char* arg, struct argp_state*)
|
|||
// because print_lbtt will raise an exception anyway. The
|
||||
// error message is slightly better in the current way.
|
||||
if (arg && (arg[0] != 't' || arg[1] != 0))
|
||||
error(2, 0, "unknown argument for --lbtt: '%s'", arg);
|
||||
error(2, 0, "unknown argument for --lbtt: '%s'", arg);
|
||||
break;
|
||||
case OPT_NAME:
|
||||
opt_name = arg;
|
||||
break;
|
||||
case OPT_STATS:
|
||||
if (!*arg)
|
||||
error(2, 0, "empty format string for --stats");
|
||||
error(2, 0, "empty format string for --stats");
|
||||
stats = arg;
|
||||
automaton_format = Stats;
|
||||
break;
|
||||
|
|
@ -288,23 +288,23 @@ void setup_default_output_format()
|
|||
if (auto val = getenv("SPOT_DEFAULT_FORMAT"))
|
||||
{
|
||||
static char const *const args[] =
|
||||
{
|
||||
"dot", "hoa", "hoaf", nullptr
|
||||
};
|
||||
{
|
||||
"dot", "hoa", "hoaf", nullptr
|
||||
};
|
||||
static automaton_format_t const format[] =
|
||||
{
|
||||
Dot, Hoa, Hoa
|
||||
};
|
||||
{
|
||||
Dot, Hoa, Hoa
|
||||
};
|
||||
auto eq = strchr(val, '=');
|
||||
if (eq)
|
||||
{
|
||||
val = strndup(val, eq - val);
|
||||
automaton_format_opt = eq + 1;
|
||||
}
|
||||
{
|
||||
val = strndup(val, eq - val);
|
||||
automaton_format_opt = eq + 1;
|
||||
}
|
||||
ARGMATCH_VERIFY(args, format);
|
||||
automaton_format = XARGMATCH("SPOT_DEFAULT_FORMAT", val, args, format);
|
||||
if (eq)
|
||||
free(val);
|
||||
free(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -320,24 +320,24 @@ automaton_printer::automaton_printer(stat_style input)
|
|||
|
||||
void
|
||||
automaton_printer::print(const spot::twa_graph_ptr& aut,
|
||||
spot::formula f,
|
||||
// Input location for errors and statistics.
|
||||
const char* filename,
|
||||
int loc,
|
||||
// Time and input automaton for statistics
|
||||
double time,
|
||||
const spot::const_parsed_aut_ptr& haut,
|
||||
const char* csv_prefix,
|
||||
const char* csv_suffix)
|
||||
spot::formula f,
|
||||
// Input location for errors and statistics.
|
||||
const char* filename,
|
||||
int loc,
|
||||
// Time and input automaton for statistics
|
||||
double time,
|
||||
const spot::const_parsed_aut_ptr& haut,
|
||||
const char* csv_prefix,
|
||||
const char* csv_suffix)
|
||||
{
|
||||
if (opt_check)
|
||||
{
|
||||
if (opt_check & check_stutter)
|
||||
spot::check_stutter_invariance(aut, f);
|
||||
spot::check_stutter_invariance(aut, f);
|
||||
if (opt_check & check_unambiguous)
|
||||
spot::check_unambiguous(aut);
|
||||
spot::check_unambiguous(aut);
|
||||
if (opt_check & check_strength)
|
||||
spot::check_strength(aut);
|
||||
spot::check_strength(aut);
|
||||
}
|
||||
|
||||
// Name the output automaton.
|
||||
|
|
@ -353,11 +353,11 @@ automaton_printer::print(const spot::twa_graph_ptr& aut,
|
|||
{
|
||||
outputname.str("");
|
||||
outputnamer.print(haut, aut, f, filename, loc, time,
|
||||
csv_prefix, csv_suffix);
|
||||
csv_prefix, csv_suffix);
|
||||
std::string fname = outputname.str();
|
||||
auto p = outputfiles.emplace(fname, nullptr);
|
||||
if (p.second)
|
||||
p.first->second.reset(new output_file(fname.c_str()));
|
||||
p.first->second.reset(new output_file(fname.c_str()));
|
||||
out = &p.first->second->ostream();
|
||||
}
|
||||
|
||||
|
|
@ -383,7 +383,7 @@ automaton_printer::print(const spot::twa_graph_ptr& aut,
|
|||
case Stats:
|
||||
statistics.set_output(*out);
|
||||
statistics.print(haut, aut, f, filename, loc, time,
|
||||
csv_prefix, csv_suffix) << '\n';
|
||||
csv_prefix, csv_suffix) << '\n';
|
||||
break;
|
||||
}
|
||||
flush_cout();
|
||||
|
|
|
|||
|
|
@ -75,25 +75,25 @@ class hoa_stat_printer: protected spot::stat_printer
|
|||
{
|
||||
public:
|
||||
hoa_stat_printer(std::ostream& os, const char* format,
|
||||
stat_style input = no_input)
|
||||
stat_style input = no_input)
|
||||
: spot::stat_printer(os, format)
|
||||
{
|
||||
if (input == aut_input)
|
||||
{
|
||||
declare('A', &haut_acc_);
|
||||
declare('C', &haut_scc_);
|
||||
declare('E', &haut_edges_);
|
||||
declare('G', &haut_gen_acc_);
|
||||
declare('M', &haut_name_);
|
||||
declare('S', &haut_states_);
|
||||
declare('T', &haut_trans_);
|
||||
declare('A', &haut_acc_);
|
||||
declare('C', &haut_scc_);
|
||||
declare('E', &haut_edges_);
|
||||
declare('G', &haut_gen_acc_);
|
||||
declare('M', &haut_name_);
|
||||
declare('S', &haut_states_);
|
||||
declare('T', &haut_trans_);
|
||||
}
|
||||
declare('<', &csv_prefix_);
|
||||
declare('>', &csv_suffix_);
|
||||
declare('F', &filename_);
|
||||
declare('L', &location_);
|
||||
if (input != ltl_input)
|
||||
declare('f', &filename_); // Override the formula printer.
|
||||
declare('f', &filename_); // Override the formula printer.
|
||||
declare('m', &aut_name_);
|
||||
declare('w', &aut_word_);
|
||||
}
|
||||
|
|
@ -107,93 +107,93 @@ public:
|
|||
/// to be output.
|
||||
std::ostream&
|
||||
print(const spot::const_parsed_aut_ptr& haut,
|
||||
const spot::const_twa_graph_ptr& aut,
|
||||
spot::formula f,
|
||||
const char* filename, int loc, double run_time,
|
||||
const char* csv_prefix, const char* csv_suffix)
|
||||
const spot::const_twa_graph_ptr& aut,
|
||||
spot::formula f,
|
||||
const char* filename, int loc, double run_time,
|
||||
const char* csv_prefix, const char* csv_suffix)
|
||||
{
|
||||
filename_ = filename ? filename : "";
|
||||
csv_prefix_ = csv_prefix ? csv_prefix : "";
|
||||
csv_suffix_ = csv_suffix ? csv_suffix : "";
|
||||
if (loc >= 0 && has('L'))
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << loc;
|
||||
location_ = os.str();
|
||||
std::ostringstream os;
|
||||
os << loc;
|
||||
location_ = os.str();
|
||||
}
|
||||
if (haut)
|
||||
{
|
||||
if (loc < 0 && has('L'))
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << haut->loc;
|
||||
location_ = os.str();
|
||||
}
|
||||
if (loc < 0 && has('L'))
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << haut->loc;
|
||||
location_ = os.str();
|
||||
}
|
||||
|
||||
if (has('T'))
|
||||
{
|
||||
spot::twa_sub_statistics s = sub_stats_reachable(haut->aut);
|
||||
haut_states_ = s.states;
|
||||
haut_edges_ = s.edges;
|
||||
haut_trans_ = s.transitions;
|
||||
}
|
||||
else if (has('E'))
|
||||
{
|
||||
spot::twa_sub_statistics s = sub_stats_reachable(haut->aut);
|
||||
haut_states_ = s.states;
|
||||
haut_edges_ = s.edges;
|
||||
}
|
||||
if (has('M'))
|
||||
{
|
||||
auto n = haut->aut->get_named_prop<std::string>("automaton-name");
|
||||
if (n)
|
||||
haut_name_ = *n;
|
||||
else
|
||||
haut_name_.val().clear();
|
||||
}
|
||||
if (has('S'))
|
||||
haut_states_ = haut->aut->num_states();
|
||||
if (has('T'))
|
||||
{
|
||||
spot::twa_sub_statistics s = sub_stats_reachable(haut->aut);
|
||||
haut_states_ = s.states;
|
||||
haut_edges_ = s.edges;
|
||||
haut_trans_ = s.transitions;
|
||||
}
|
||||
else if (has('E'))
|
||||
{
|
||||
spot::twa_sub_statistics s = sub_stats_reachable(haut->aut);
|
||||
haut_states_ = s.states;
|
||||
haut_edges_ = s.edges;
|
||||
}
|
||||
if (has('M'))
|
||||
{
|
||||
auto n = haut->aut->get_named_prop<std::string>("automaton-name");
|
||||
if (n)
|
||||
haut_name_ = *n;
|
||||
else
|
||||
haut_name_.val().clear();
|
||||
}
|
||||
if (has('S'))
|
||||
haut_states_ = haut->aut->num_states();
|
||||
|
||||
if (has('A'))
|
||||
haut_acc_ = haut->aut->acc().num_sets();
|
||||
if (has('A'))
|
||||
haut_acc_ = haut->aut->acc().num_sets();
|
||||
|
||||
if (has('C'))
|
||||
haut_scc_ = spot::scc_info(haut->aut).scc_count();
|
||||
if (has('C'))
|
||||
haut_scc_ = spot::scc_info(haut->aut).scc_count();
|
||||
|
||||
if (has('G'))
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << haut->aut->get_acceptance();
|
||||
haut_gen_acc_ = os.str();
|
||||
}
|
||||
if (has('G'))
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << haut->aut->get_acceptance();
|
||||
haut_gen_acc_ = os.str();
|
||||
}
|
||||
}
|
||||
|
||||
if (has('m'))
|
||||
{
|
||||
auto n = aut->get_named_prop<std::string>("automaton-name");
|
||||
if (n)
|
||||
aut_name_ = *n;
|
||||
else
|
||||
aut_name_.val().clear();
|
||||
}
|
||||
{
|
||||
auto n = aut->get_named_prop<std::string>("automaton-name");
|
||||
if (n)
|
||||
aut_name_ = *n;
|
||||
else
|
||||
aut_name_.val().clear();
|
||||
}
|
||||
if (has('w'))
|
||||
{
|
||||
auto res = spot::couvreur99(aut)->check();
|
||||
if (res)
|
||||
{
|
||||
auto run = res->accepting_run();
|
||||
assert(run);
|
||||
spot::twa_word w(run->reduce());
|
||||
w.simplify();
|
||||
std::ostringstream out;
|
||||
out << w;
|
||||
aut_word_ = out.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
aut_word_.val().clear();
|
||||
}
|
||||
}
|
||||
{
|
||||
auto res = spot::couvreur99(aut)->check();
|
||||
if (res)
|
||||
{
|
||||
auto run = res->accepting_run();
|
||||
assert(run);
|
||||
spot::twa_word w(run->reduce());
|
||||
w.simplify();
|
||||
std::ostringstream out;
|
||||
out << w;
|
||||
aut_word_ = out.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
aut_word_.val().clear();
|
||||
}
|
||||
}
|
||||
|
||||
return this->spot::stat_printer::print(aut, f, run_time);
|
||||
}
|
||||
|
|
@ -230,15 +230,15 @@ public:
|
|||
|
||||
void
|
||||
print(const spot::twa_graph_ptr& aut,
|
||||
spot::formula f = nullptr,
|
||||
// Input location for errors and statistics.
|
||||
const char* filename = nullptr,
|
||||
int loc = -1,
|
||||
// Time and input automaton for statistics
|
||||
double time = 0.0,
|
||||
const spot::const_parsed_aut_ptr& haut = nullptr,
|
||||
const char* csv_prefix = nullptr,
|
||||
const char* csv_suffix = nullptr);
|
||||
spot::formula f = nullptr,
|
||||
// Input location for errors and statistics.
|
||||
const char* filename = nullptr,
|
||||
int loc = -1,
|
||||
// Time and input automaton for statistics
|
||||
double time = 0.0,
|
||||
const spot::const_parsed_aut_ptr& haut = nullptr,
|
||||
const char* csv_prefix = nullptr,
|
||||
const char* csv_suffix = nullptr);
|
||||
|
||||
void add_stat(char c, const spot::printable* p);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ static const argp_option options[] =
|
|||
};
|
||||
|
||||
const struct argp finput_argp = { options, parse_opt_finput,
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
|
||||
int
|
||||
parse_opt_finput(int key, char* arg, struct argp_state*)
|
||||
|
|
@ -105,15 +105,15 @@ job_processor::~job_processor()
|
|||
|
||||
int
|
||||
job_processor::process_string(const std::string& input,
|
||||
const char* filename,
|
||||
int linenum)
|
||||
const char* filename,
|
||||
int linenum)
|
||||
{
|
||||
auto pf = parse_formula(input);
|
||||
|
||||
if (!pf.f || !pf.errors.empty())
|
||||
{
|
||||
if (filename)
|
||||
error_at_line(0, 0, filename, linenum, "parse error:");
|
||||
error_at_line(0, 0, filename, linenum, "parse error:");
|
||||
pf.format_errors(std::cerr);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -122,7 +122,7 @@ job_processor::process_string(const std::string& input,
|
|||
|
||||
int
|
||||
job_processor::process_stream(std::istream& is,
|
||||
const char* filename)
|
||||
const char* filename)
|
||||
{
|
||||
int error = 0;
|
||||
int linenum = 1;
|
||||
|
|
@ -141,148 +141,148 @@ job_processor::process_stream(std::istream& is,
|
|||
while (!abort_run && std::getline(is, line))
|
||||
if (!line.empty())
|
||||
{
|
||||
if (col_to_read == 0)
|
||||
{
|
||||
error |= process_string(line, filename, linenum++);
|
||||
}
|
||||
else // We are reading column COL_TO_READ in a CSV file.
|
||||
{
|
||||
// If the line we have read contains an odd number
|
||||
// of double-quotes, then it is an incomplete CSV line
|
||||
// that should be completed by the next lines.
|
||||
unsigned dquotes = 0;
|
||||
std::string fullline;
|
||||
unsigned csvlines = 0;
|
||||
do
|
||||
{
|
||||
++csvlines;
|
||||
size_t s = line.size();
|
||||
for (unsigned i = 0; i < s; ++i)
|
||||
dquotes += line[i] == '"';
|
||||
if (fullline.empty())
|
||||
fullline = line;
|
||||
else
|
||||
(fullline += '\n') += line;
|
||||
if (!(dquotes &= 1))
|
||||
break;
|
||||
}
|
||||
while (std::getline(is, line));
|
||||
if (dquotes)
|
||||
error_at_line(2, errno, filename, linenum,
|
||||
"mismatched double-quote, "
|
||||
"reached EOF while parsing this line");
|
||||
if (col_to_read == 0)
|
||||
{
|
||||
error |= process_string(line, filename, linenum++);
|
||||
}
|
||||
else // We are reading column COL_TO_READ in a CSV file.
|
||||
{
|
||||
// If the line we have read contains an odd number
|
||||
// of double-quotes, then it is an incomplete CSV line
|
||||
// that should be completed by the next lines.
|
||||
unsigned dquotes = 0;
|
||||
std::string fullline;
|
||||
unsigned csvlines = 0;
|
||||
do
|
||||
{
|
||||
++csvlines;
|
||||
size_t s = line.size();
|
||||
for (unsigned i = 0; i < s; ++i)
|
||||
dquotes += line[i] == '"';
|
||||
if (fullline.empty())
|
||||
fullline = line;
|
||||
else
|
||||
(fullline += '\n') += line;
|
||||
if (!(dquotes &= 1))
|
||||
break;
|
||||
}
|
||||
while (std::getline(is, line));
|
||||
if (dquotes)
|
||||
error_at_line(2, errno, filename, linenum,
|
||||
"mismatched double-quote, "
|
||||
"reached EOF while parsing this line");
|
||||
|
||||
// Now that we have a full CSV line, extract the right
|
||||
// column.
|
||||
// Now that we have a full CSV line, extract the right
|
||||
// column.
|
||||
|
||||
const char* str = fullline.c_str();
|
||||
const char* col1_start = str;
|
||||
// Delimiters for the extracted column.
|
||||
const char* coln_start = str;
|
||||
const char* coln_end = nullptr;
|
||||
// The current column. (1-based)
|
||||
int colnum = 1;
|
||||
// Whether we are parsing a double-quoted string.
|
||||
bool instring = false;
|
||||
// Note that RFC 4180 has strict rules about
|
||||
// double-quotes: ① if a field is double-quoted, the first
|
||||
// and last characters of the field should be
|
||||
// double-quotes; ② if a field contains a double-quote
|
||||
// then it should be double quoted, and the occurrences
|
||||
// of double-quotes should be doubled. Therefore a CSV file
|
||||
// may no contain a line such as:
|
||||
// foo,bar"ba""z",12
|
||||
// Tools have different interpretation of such a line.
|
||||
// For instance Python's pandas.read_csv() function will
|
||||
// load the second field verbatim as the string 'bar"ba""z"',
|
||||
// while R's read.csv() function will load it as the
|
||||
// string 'barba"z'. We use this second interpretation, because
|
||||
// it also makes it possible to parse CSVs fields formatted
|
||||
// with leading spaces (often for cosmetic purpose). When
|
||||
// extracting the second field of
|
||||
// foo, "ba""z", 12
|
||||
// we will return ' baz' and the leading space will be ignored
|
||||
// by our LTL formula parser.
|
||||
while (*str)
|
||||
{
|
||||
switch (*str)
|
||||
{
|
||||
case '"':
|
||||
// Doubled double-quotes are used to escape
|
||||
// double-quotes.
|
||||
if (instring && str[1] == '"')
|
||||
++str;
|
||||
else
|
||||
instring = !instring;
|
||||
break;
|
||||
case ',':
|
||||
if (!instring)
|
||||
{
|
||||
if (col_to_read == colnum)
|
||||
coln_end = str;
|
||||
++colnum;
|
||||
if (col_to_read == colnum)
|
||||
coln_start = str + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Once we have the end delimiter for our target
|
||||
// column, we have all we need.
|
||||
if (coln_end)
|
||||
break;
|
||||
++str;
|
||||
}
|
||||
if (!*str)
|
||||
{
|
||||
if (colnum != col_to_read)
|
||||
// Skip this line as it has no enough columns.
|
||||
continue;
|
||||
else
|
||||
// The target columns ends at the end of the line.
|
||||
coln_end = str;
|
||||
}
|
||||
const char* str = fullline.c_str();
|
||||
const char* col1_start = str;
|
||||
// Delimiters for the extracted column.
|
||||
const char* coln_start = str;
|
||||
const char* coln_end = nullptr;
|
||||
// The current column. (1-based)
|
||||
int colnum = 1;
|
||||
// Whether we are parsing a double-quoted string.
|
||||
bool instring = false;
|
||||
// Note that RFC 4180 has strict rules about
|
||||
// double-quotes: ① if a field is double-quoted, the first
|
||||
// and last characters of the field should be
|
||||
// double-quotes; ② if a field contains a double-quote
|
||||
// then it should be double quoted, and the occurrences
|
||||
// of double-quotes should be doubled. Therefore a CSV file
|
||||
// may no contain a line such as:
|
||||
// foo,bar"ba""z",12
|
||||
// Tools have different interpretation of such a line.
|
||||
// For instance Python's pandas.read_csv() function will
|
||||
// load the second field verbatim as the string 'bar"ba""z"',
|
||||
// while R's read.csv() function will load it as the
|
||||
// string 'barba"z'. We use this second interpretation, because
|
||||
// it also makes it possible to parse CSVs fields formatted
|
||||
// with leading spaces (often for cosmetic purpose). When
|
||||
// extracting the second field of
|
||||
// foo, "ba""z", 12
|
||||
// we will return ' baz' and the leading space will be ignored
|
||||
// by our LTL formula parser.
|
||||
while (*str)
|
||||
{
|
||||
switch (*str)
|
||||
{
|
||||
case '"':
|
||||
// Doubled double-quotes are used to escape
|
||||
// double-quotes.
|
||||
if (instring && str[1] == '"')
|
||||
++str;
|
||||
else
|
||||
instring = !instring;
|
||||
break;
|
||||
case ',':
|
||||
if (!instring)
|
||||
{
|
||||
if (col_to_read == colnum)
|
||||
coln_end = str;
|
||||
++colnum;
|
||||
if (col_to_read == colnum)
|
||||
coln_start = str + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Once we have the end delimiter for our target
|
||||
// column, we have all we need.
|
||||
if (coln_end)
|
||||
break;
|
||||
++str;
|
||||
}
|
||||
if (!*str)
|
||||
{
|
||||
if (colnum != col_to_read)
|
||||
// Skip this line as it has no enough columns.
|
||||
continue;
|
||||
else
|
||||
// The target columns ends at the end of the line.
|
||||
coln_end = str;
|
||||
}
|
||||
|
||||
// Skip the line if it has an empty field.
|
||||
if (coln_start == coln_end)
|
||||
continue;
|
||||
// Skip the line if it has an empty field.
|
||||
if (coln_start == coln_end)
|
||||
continue;
|
||||
|
||||
// save the contents before and after that columns for the
|
||||
// %< and %> escapes (ignoring the trailing and leading
|
||||
// commas).
|
||||
prefix = (col_to_read != 1) ?
|
||||
strndup(col1_start, coln_start - col1_start - 1) : nullptr;
|
||||
suffix = (*coln_end != 0) ? strdup(coln_end + 1) : nullptr;
|
||||
std::string field(coln_start, coln_end);
|
||||
// Remove double-quotes if any.
|
||||
if (field.find('"') != std::string::npos)
|
||||
{
|
||||
unsigned dst = 0;
|
||||
bool instring = false;
|
||||
for (; coln_start != coln_end; ++coln_start)
|
||||
if (*coln_start == '"')
|
||||
// A doubled double-quote instead a double-quoted
|
||||
// string is an escaped double-quote.
|
||||
if (instring && coln_start[1] == '"')
|
||||
field[dst++] = *++coln_start;
|
||||
else
|
||||
instring = !instring;
|
||||
else
|
||||
field[dst++] = *coln_start;
|
||||
field.resize(dst);
|
||||
}
|
||||
error |= process_string(field, filename, linenum);
|
||||
linenum += csvlines;
|
||||
if (prefix)
|
||||
{
|
||||
free(prefix);
|
||||
prefix = nullptr;
|
||||
}
|
||||
if (suffix)
|
||||
{
|
||||
free(suffix);
|
||||
suffix = nullptr;
|
||||
}
|
||||
}
|
||||
// save the contents before and after that columns for the
|
||||
// %< and %> escapes (ignoring the trailing and leading
|
||||
// commas).
|
||||
prefix = (col_to_read != 1) ?
|
||||
strndup(col1_start, coln_start - col1_start - 1) : nullptr;
|
||||
suffix = (*coln_end != 0) ? strdup(coln_end + 1) : nullptr;
|
||||
std::string field(coln_start, coln_end);
|
||||
// Remove double-quotes if any.
|
||||
if (field.find('"') != std::string::npos)
|
||||
{
|
||||
unsigned dst = 0;
|
||||
bool instring = false;
|
||||
for (; coln_start != coln_end; ++coln_start)
|
||||
if (*coln_start == '"')
|
||||
// A doubled double-quote instead a double-quoted
|
||||
// string is an escaped double-quote.
|
||||
if (instring && coln_start[1] == '"')
|
||||
field[dst++] = *++coln_start;
|
||||
else
|
||||
instring = !instring;
|
||||
else
|
||||
field[dst++] = *coln_start;
|
||||
field.resize(dst);
|
||||
}
|
||||
error |= process_string(field, filename, linenum);
|
||||
linenum += csvlines;
|
||||
if (prefix)
|
||||
{
|
||||
free(prefix);
|
||||
prefix = nullptr;
|
||||
}
|
||||
if (suffix)
|
||||
{
|
||||
free(suffix);
|
||||
suffix = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
|
@ -315,23 +315,23 @@ job_processor::process_file(const char* filename)
|
|||
long int col = strtol(slash + 1, &end, 10);
|
||||
// strtol ate all remaining characters and NN is positive
|
||||
if (errno == 0 && !*end && col != 0)
|
||||
{
|
||||
col_to_read = col;
|
||||
if (real_filename)
|
||||
free(real_filename);
|
||||
real_filename = strndup(filename, slash - filename);
|
||||
{
|
||||
col_to_read = col;
|
||||
if (real_filename)
|
||||
free(real_filename);
|
||||
real_filename = strndup(filename, slash - filename);
|
||||
|
||||
// Special case for stdin.
|
||||
if (real_filename[0] == '-' && real_filename[1] == 0)
|
||||
return process_stream(std::cin, real_filename);
|
||||
// Special case for stdin.
|
||||
if (real_filename[0] == '-' && real_filename[1] == 0)
|
||||
return process_stream(std::cin, real_filename);
|
||||
|
||||
std::ifstream input(real_filename);
|
||||
if (input)
|
||||
return process_stream(input, real_filename);
|
||||
std::ifstream input(real_filename);
|
||||
if (input)
|
||||
return process_stream(input, real_filename);
|
||||
|
||||
error(2, errno, "cannot open '%s' nor '%s'",
|
||||
filename, real_filename);
|
||||
}
|
||||
error(2, errno, "cannot open '%s' nor '%s'",
|
||||
filename, real_filename);
|
||||
}
|
||||
}
|
||||
|
||||
error(2, saved_errno, "cannot open '%s'", filename);
|
||||
|
|
@ -345,11 +345,11 @@ job_processor::run()
|
|||
for (auto& j: jobs)
|
||||
{
|
||||
if (!j.file_p)
|
||||
error |= process_string(j.str);
|
||||
error |= process_string(j.str);
|
||||
else
|
||||
error |= process_file(j.str);
|
||||
error |= process_file(j.str);
|
||||
if (abort_run)
|
||||
break;
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
struct job
|
||||
{
|
||||
const char* str;
|
||||
bool file_p; // true if str is a filename, false if it is a formula
|
||||
bool file_p; // true if str is a filename, false if it is a formula
|
||||
|
||||
job(const char* str, bool file_p)
|
||||
: str(str), file_p(file_p)
|
||||
|
|
@ -58,11 +58,11 @@ public:
|
|||
|
||||
virtual int
|
||||
process_formula(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0) = 0;
|
||||
const char* filename = nullptr, int linenum = 0) = 0;
|
||||
|
||||
virtual int
|
||||
process_string(const std::string& str,
|
||||
const char* filename = nullptr, int linenum = 0);
|
||||
const char* filename = nullptr, int linenum = 0);
|
||||
virtual int
|
||||
process_stream(std::istream& is, const char* filename);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ spot::twa_graph_ptr
|
|||
read_automaton(const char* filename, spot::bdd_dict_ptr& dict)
|
||||
{
|
||||
auto p = spot::parse_aut(filename, dict,
|
||||
spot::default_environment::instance(),
|
||||
opt_parse);
|
||||
spot::default_environment::instance(),
|
||||
opt_parse);
|
||||
if (p->format_errors(std::cerr))
|
||||
error(2, 0, "failed to read automaton from %s", filename);
|
||||
if (p->aborted)
|
||||
|
|
@ -86,5 +86,5 @@ parse_opt_hoaread(int key, char* arg, struct argp_state*)
|
|||
|
||||
|
||||
const struct argp hoaread_argp = { options, parse_opt_hoaread,
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
|
|
|
|||
|
|
@ -65,13 +65,13 @@ static const argp_option options[] =
|
|||
};
|
||||
|
||||
const struct argp output_argp = { options, parse_opt_output,
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
|
||||
static
|
||||
void
|
||||
report_not_ltl(spot::formula f,
|
||||
const char* filename, int linenum, const char* syn)
|
||||
const char* filename, int linenum, const char* syn)
|
||||
{
|
||||
std::string s = spot::str_psl(f);
|
||||
static const char msg[] =
|
||||
|
|
@ -84,30 +84,30 @@ report_not_ltl(spot::formula f,
|
|||
|
||||
std::ostream&
|
||||
stream_formula(std::ostream& out,
|
||||
spot::formula f, const char* filename, int linenum)
|
||||
spot::formula f, const char* filename, int linenum)
|
||||
{
|
||||
switch (output_format)
|
||||
{
|
||||
case lbt_output:
|
||||
if (f.is_ltl_formula())
|
||||
spot::print_lbt_ltl(out, f);
|
||||
spot::print_lbt_ltl(out, f);
|
||||
else
|
||||
report_not_ltl(f, filename, linenum, "LBT");
|
||||
report_not_ltl(f, filename, linenum, "LBT");
|
||||
break;
|
||||
case spot_output:
|
||||
spot::print_psl(out, f, full_parenth);
|
||||
break;
|
||||
case spin_output:
|
||||
if (f.is_ltl_formula())
|
||||
spot::print_spin_ltl(out, f, full_parenth);
|
||||
spot::print_spin_ltl(out, f, full_parenth);
|
||||
else
|
||||
report_not_ltl(f, filename, linenum, "Spin");
|
||||
report_not_ltl(f, filename, linenum, "Spin");
|
||||
break;
|
||||
case wring_output:
|
||||
if (f.is_ltl_formula())
|
||||
spot::print_wring_ltl(out, f);
|
||||
spot::print_wring_ltl(out, f);
|
||||
else
|
||||
report_not_ltl(f, filename, linenum, "Wring");
|
||||
report_not_ltl(f, filename, linenum, "Wring");
|
||||
break;
|
||||
case utf8_output:
|
||||
spot::print_utf8_psl(out, f, full_parenth);
|
||||
|
|
@ -124,8 +124,8 @@ stream_formula(std::ostream& out,
|
|||
|
||||
static void
|
||||
stream_escapable_formula(std::ostream& os,
|
||||
spot::formula f,
|
||||
const char* filename, int linenum)
|
||||
spot::formula f,
|
||||
const char* filename, int linenum)
|
||||
{
|
||||
if (escape_csv)
|
||||
{
|
||||
|
|
@ -260,17 +260,17 @@ parse_opt_output(int key, char* arg, struct argp_state*)
|
|||
|
||||
static void
|
||||
output_formula(std::ostream& out,
|
||||
spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0,
|
||||
const char* prefix = nullptr, const char* suffix = nullptr)
|
||||
spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0,
|
||||
const char* prefix = nullptr, const char* suffix = nullptr)
|
||||
{
|
||||
if (!format)
|
||||
{
|
||||
if (prefix)
|
||||
out << prefix << ',';
|
||||
out << prefix << ',';
|
||||
stream_escapable_formula(out, f, filename, linenum);
|
||||
if (suffix)
|
||||
out << ',' << suffix;
|
||||
out << ',' << suffix;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -287,14 +287,14 @@ void
|
|||
|
||||
void
|
||||
output_formula_checked(spot::formula f,
|
||||
const char* filename, int linenum,
|
||||
const char* prefix, const char* suffix)
|
||||
const char* filename, int linenum,
|
||||
const char* prefix, const char* suffix)
|
||||
{
|
||||
if (output_format == count_output)
|
||||
{
|
||||
if (outputnamer)
|
||||
throw std::runtime_error
|
||||
("options --output and --count are incompatible");
|
||||
throw std::runtime_error
|
||||
("options --output and --count are incompatible");
|
||||
return;
|
||||
}
|
||||
if (output_format == quiet_output)
|
||||
|
|
@ -308,7 +308,7 @@ output_formula_checked(spot::formula f,
|
|||
std::string fname = outputname.str();
|
||||
auto p = outputfiles.emplace(fname, nullptr);
|
||||
if (p.second)
|
||||
p.first->second.reset(new output_file(fname.c_str()));
|
||||
p.first->second.reset(new output_file(fname.c_str()));
|
||||
out = &p.first->second->ostream();
|
||||
}
|
||||
output_formula(*out, f, filename, linenum, prefix, suffix);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include "common_file.hh"
|
||||
|
||||
enum output_format_t { spot_output, spin_output, utf8_output,
|
||||
lbt_output, wring_output, latex_output,
|
||||
lbt_output, wring_output, latex_output,
|
||||
quiet_output, count_output };
|
||||
extern output_format_t output_format;
|
||||
extern bool full_parenth;
|
||||
|
|
@ -43,12 +43,12 @@ int parse_opt_output(int key, char* arg, struct argp_state* state);
|
|||
// Low-level output
|
||||
std::ostream&
|
||||
stream_formula(std::ostream& out,
|
||||
spot::formula f, const char* filename, int linenum);
|
||||
spot::formula f, const char* filename, int linenum);
|
||||
|
||||
void output_formula_checked(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0,
|
||||
const char* prefix = nullptr,
|
||||
const char* suffix = nullptr);
|
||||
const char* filename = nullptr, int linenum = 0,
|
||||
const char* prefix = nullptr,
|
||||
const char* suffix = nullptr);
|
||||
|
||||
|
||||
class printable_formula:
|
||||
|
|
@ -72,15 +72,15 @@ public:
|
|||
aut_stat_printer(std::ostream& os, const char* format)
|
||||
: spot::stat_printer(os, format)
|
||||
{
|
||||
declare('f', &formula_); // Override the formula printer.
|
||||
declare('f', &formula_); // Override the formula printer.
|
||||
}
|
||||
|
||||
using spot::formater::set_output;
|
||||
|
||||
std::ostream&
|
||||
print(const spot::const_twa_graph_ptr& aut,
|
||||
spot::formula f = nullptr,
|
||||
double run_time = -1.)
|
||||
spot::formula f = nullptr,
|
||||
double run_time = -1.)
|
||||
{
|
||||
formula_ = f;
|
||||
return this->spot::stat_printer::print(aut, f, run_time);
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ parse_opt_post(int key, char*, struct argp_state*)
|
|||
break;
|
||||
case OPT_TGBA:
|
||||
if (automaton_format == Spin)
|
||||
error(2, 0, "--spin and --tgba are incompatible");
|
||||
error(2, 0, "--spin and --tgba are incompatible");
|
||||
type = spot::postprocessor::TGBA;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -165,7 +165,7 @@ parse_opt_post(int key, char*, struct argp_state*)
|
|||
}
|
||||
|
||||
const struct argp post_argp = { options, parse_opt_post,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
const struct argp post_argp_disabled = { options_disabled, parse_opt_post,
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include <spot/twaalgos/postproc.hh>
|
||||
#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 spot::postprocessor::output_type type;
|
||||
|
|
|
|||
|
|
@ -24,21 +24,21 @@
|
|||
|
||||
#define OPT_R 'r'
|
||||
|
||||
#define DECLARE_OPT_R \
|
||||
{ "simplify", OPT_R, "LEVEL", OPTION_ARG_OPTIONAL, \
|
||||
"simplify formulas according to LEVEL (see below); LEVEL is " \
|
||||
#define DECLARE_OPT_R \
|
||||
{ "simplify", OPT_R, "LEVEL", OPTION_ARG_OPTIONAL, \
|
||||
"simplify formulas according to LEVEL (see below); LEVEL is " \
|
||||
"set to 3 if omitted", 0 }
|
||||
|
||||
#define LEVEL_DOC(g) \
|
||||
{ nullptr, 0, nullptr, 0, \
|
||||
"The simplification LEVEL may be set as follows.", g }, \
|
||||
{ " 0", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
|
||||
"No rewriting", 0 }, \
|
||||
{ " 1", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
|
||||
"basic rewritings and eventual/universal rules", 0 }, \
|
||||
{ " 2", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
|
||||
"additional syntactic implication rules", 0 }, \
|
||||
{ " 3", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
|
||||
#define LEVEL_DOC(g) \
|
||||
{ nullptr, 0, nullptr, 0, \
|
||||
"The simplification LEVEL may be set as follows.", g }, \
|
||||
{ " 0", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
|
||||
"No rewriting", 0 }, \
|
||||
{ " 1", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
|
||||
"basic rewritings and eventual/universal rules", 0 }, \
|
||||
{ " 2", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
|
||||
"additional syntactic implication rules", 0 }, \
|
||||
{ " 3", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, \
|
||||
"better implications using containment", 0 }
|
||||
|
||||
extern int simplification_level;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ parse_range(const char* str, int missing_left, int missing_right)
|
|||
// No leading number. It's OK as long as the string is not
|
||||
// empty.
|
||||
if (!*end)
|
||||
error(1, 0, "invalid empty range");
|
||||
error(1, 0, "invalid empty range");
|
||||
res.min = missing_left;
|
||||
}
|
||||
if (!*end)
|
||||
|
|
@ -54,24 +54,24 @@ parse_range(const char* str, int missing_left, int missing_right)
|
|||
{
|
||||
// Skip : or ..
|
||||
if (end[0] == ':')
|
||||
++end;
|
||||
++end;
|
||||
else if (end[0] == '.' && end[1] == '.')
|
||||
end += 2;
|
||||
end += 2;
|
||||
|
||||
if (!*end && missing_right != 0)
|
||||
{
|
||||
res.max = missing_right;
|
||||
}
|
||||
{
|
||||
res.max = missing_right;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse the next integer.
|
||||
char* end2;
|
||||
res.max = strtol(end, &end2, 10);
|
||||
if (end == end2)
|
||||
error(1, 0, "invalid range '%s' (missing end?)", str);
|
||||
if (*end2)
|
||||
error(1, 0, "invalid range '%s' (trailing garbage?)", str);
|
||||
}
|
||||
{
|
||||
// Parse the next integer.
|
||||
char* end2;
|
||||
res.max = strtol(end, &end2, 10);
|
||||
if (end == end2)
|
||||
error(1, 0, "invalid range '%s' (missing end?)", str);
|
||||
if (*end2)
|
||||
error(1, 0, "invalid range '%s' (trailing garbage?)", str);
|
||||
}
|
||||
}
|
||||
|
||||
if (res.min < 0 || res.max < 0)
|
||||
|
|
|
|||
|
|
@ -19,15 +19,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#define RANGE_DOC \
|
||||
{ nullptr, 0, nullptr, 0, \
|
||||
"RANGE may have one of the following forms: 'INT', " \
|
||||
#define RANGE_DOC \
|
||||
{ nullptr, 0, nullptr, 0, \
|
||||
"RANGE may have one of the following forms: 'INT', " \
|
||||
"'INT..INT', or '..INT'.\nIn the latter case, the missing number " \
|
||||
"is assumed to be 1.", 0 }
|
||||
|
||||
#define RANGE_DOC_FULL \
|
||||
{ nullptr, 0, nullptr, 0, \
|
||||
"RANGE may have one of the following forms: 'INT', " \
|
||||
#define RANGE_DOC_FULL \
|
||||
{ nullptr, 0, nullptr, 0, \
|
||||
"RANGE may have one of the following forms: 'INT', " \
|
||||
"'INT..INT', '..INT', or 'INT..'", 0 }
|
||||
|
||||
struct range
|
||||
|
|
@ -47,4 +47,4 @@ struct range
|
|||
// values. Additionally, if missing_right == 0, then the INT.. form
|
||||
// is disallowed.
|
||||
range parse_range(const char* str,
|
||||
int missing_left = 1, int missing_right = 0);
|
||||
int missing_left = 1, int missing_right = 0);
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ parse_opt_misc(int key, char*, struct argp_state* state)
|
|||
break;
|
||||
case OPT_USAGE:
|
||||
argp_state_help(state, state->out_stream,
|
||||
ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
|
||||
ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
|
||||
break;
|
||||
case OPT_VERSION:
|
||||
display_version(state->out_stream, state);
|
||||
|
|
@ -143,8 +143,8 @@ parse_opt_misc(int key, char*, struct argp_state* state)
|
|||
|
||||
|
||||
const struct argp misc_argp = { options, parse_opt_misc,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
|
||||
const struct argp misc_argp_hidden = { options_hidden, parse_opt_misc,
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr };
|
||||
|
|
|
|||
|
|
@ -53,17 +53,17 @@ static void show_shorthands()
|
|||
{
|
||||
std::cout
|
||||
<< ("If a COMMANDFMT does not use any %-sequence, and starts with one of\n"
|
||||
"the following words, then the string on the right is appended.\n\n");
|
||||
"the following words, then the string on the right is appended.\n\n");
|
||||
for (auto& s: shorthands)
|
||||
std::cout << " "
|
||||
<< std::left << std::setw(12) << s.prefix
|
||||
<< s.suffix << '\n';
|
||||
<< std::left << std::setw(12) << s.prefix
|
||||
<< s.suffix << '\n';
|
||||
std::cout
|
||||
<< ("\nAny {name} and directory component is skipped for the purpose of\n"
|
||||
"matching those prefixes. So for instance\n"
|
||||
" '{DRA} ~/mytools/ltl2dstar-0.5.2'\n"
|
||||
"will changed into\n"
|
||||
" '{DRA} ~/mytools/ltl2dstar-0.5.2 --output-format=hoa %L %O'\n");
|
||||
"matching those prefixes. So for instance\n"
|
||||
" '{DRA} ~/mytools/ltl2dstar-0.5.2'\n"
|
||||
"will changed into\n"
|
||||
" '{DRA} ~/mytools/ltl2dstar-0.5.2 --output-format=hoa %L %O'\n");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -76,19 +76,19 @@ translator_spec::translator_spec(const char* spec)
|
|||
const char* pos = cmd;
|
||||
unsigned count = 1;
|
||||
while (*++pos)
|
||||
{
|
||||
if (*pos == '{')
|
||||
++count;
|
||||
else if (*pos == '}')
|
||||
if (!--count)
|
||||
{
|
||||
name = strndup(cmd + 1, pos - cmd - 1);
|
||||
cmd = pos + 1;
|
||||
while (*cmd == ' ' || *cmd == '\t')
|
||||
++cmd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (*pos == '{')
|
||||
++count;
|
||||
else if (*pos == '}')
|
||||
if (!--count)
|
||||
{
|
||||
name = strndup(cmd + 1, pos - cmd - 1);
|
||||
cmd = pos + 1;
|
||||
while (*cmd == ' ' || *cmd == '\t')
|
||||
++cmd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If there is no % in the string, look for a known
|
||||
// command from our shorthand list. If we find it,
|
||||
|
|
@ -100,29 +100,29 @@ translator_spec::translator_spec(const char* spec)
|
|||
auto basename = cmd;
|
||||
auto pos = cmd;
|
||||
while (*pos)
|
||||
{
|
||||
if (*pos == '/')
|
||||
basename = pos + 1;
|
||||
else if (*pos == ' ')
|
||||
break;
|
||||
++pos;
|
||||
}
|
||||
{
|
||||
if (*pos == '/')
|
||||
basename = pos + 1;
|
||||
else if (*pos == ' ')
|
||||
break;
|
||||
++pos;
|
||||
}
|
||||
// Match a shorthand.
|
||||
for (auto& p: shorthands)
|
||||
{
|
||||
int n = strlen(p.prefix);
|
||||
if (strncmp(basename, p.prefix, n) == 0)
|
||||
{
|
||||
int m = strlen(p.suffix);
|
||||
int q = strlen(cmd);
|
||||
char* tmp = static_cast<char*>(malloc(q + m + 1));
|
||||
strcpy(tmp, cmd);
|
||||
strcpy(tmp + q, p.suffix);
|
||||
cmd = tmp;
|
||||
allocated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
int n = strlen(p.prefix);
|
||||
if (strncmp(basename, p.prefix, n) == 0)
|
||||
{
|
||||
int m = strlen(p.suffix);
|
||||
int q = strlen(cmd);
|
||||
char* tmp = static_cast<char*>(malloc(q + m + 1));
|
||||
strcpy(tmp, cmd);
|
||||
strcpy(tmp + q, p.suffix);
|
||||
cmd = tmp;
|
||||
allocated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!allocated)
|
||||
cmd = strdup(cmd);
|
||||
|
|
@ -186,7 +186,7 @@ printable_result_filename::print(std::ostream& os, const char*) const
|
|||
|
||||
|
||||
translator_runner::translator_runner(spot::bdd_dict_ptr dict,
|
||||
bool no_output_allowed)
|
||||
bool no_output_allowed)
|
||||
: dict(dict)
|
||||
{
|
||||
declare('f', &string_ltl_spot);
|
||||
|
|
@ -213,17 +213,17 @@ translator_runner::translator_runner(spot::bdd_dict_ptr dict,
|
|||
const translator_spec& t = translators[n];
|
||||
scan(t.cmd, has);
|
||||
if (!(has['f'] || has['s'] || has['l'] || has['w']
|
||||
|| has['F'] || has['S'] || has['L'] || has['W']))
|
||||
error(2, 0, "no input %%-sequence in '%s'.\n Use "
|
||||
"one of %%f,%%s,%%l,%%w,%%F,%%S,%%L,%%W to indicate how "
|
||||
"to pass the formula.", t.spec);
|
||||
|| has['F'] || has['S'] || has['L'] || has['W']))
|
||||
error(2, 0, "no input %%-sequence in '%s'.\n Use "
|
||||
"one of %%f,%%s,%%l,%%w,%%F,%%S,%%L,%%W to indicate how "
|
||||
"to pass the formula.", t.spec);
|
||||
if (!no_output_allowed
|
||||
&& !(has['O'] ||
|
||||
// backward-compatibility
|
||||
has['D'] || has['N'] || has['T'] || has['H']))
|
||||
error(2, 0, "no output %%-sequence in '%s'.\n Use "
|
||||
"%%O to indicate where the automaton is output.",
|
||||
t.spec);
|
||||
&& !(has['O'] ||
|
||||
// backward-compatibility
|
||||
has['D'] || has['N'] || has['T'] || has['H']))
|
||||
error(2, 0, "no output %%-sequence in '%s'.\n Use "
|
||||
"%%O to indicate where the automaton is output.",
|
||||
t.spec);
|
||||
// Remember the %-sequences used by all translators.
|
||||
prime(t.cmd);
|
||||
}
|
||||
|
|
@ -231,7 +231,7 @@ translator_runner::translator_runner(spot::bdd_dict_ptr dict,
|
|||
|
||||
void
|
||||
translator_runner::string_to_tmp(std::string& str, unsigned n,
|
||||
std::string& tmpname)
|
||||
std::string& tmpname)
|
||||
{
|
||||
char prefix[30];
|
||||
snprintf(prefix, sizeof prefix, "lcr-i%u-", n);
|
||||
|
|
@ -302,18 +302,18 @@ sig_handler(int sig)
|
|||
{
|
||||
timed_out = true;
|
||||
if (--alarm_on)
|
||||
{
|
||||
// Send SIGTERM to children.
|
||||
kill(-child_pid, SIGTERM);
|
||||
// Try again later if it didn't work. (alarm() will be reset
|
||||
// if it did work and the call to wait() returns)
|
||||
alarm(2);
|
||||
}
|
||||
{
|
||||
// Send SIGTERM to children.
|
||||
kill(-child_pid, SIGTERM);
|
||||
// Try again later if it didn't work. (alarm() will be reset
|
||||
// if it did work and the call to wait() returns)
|
||||
alarm(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// After a few gentle tries, really kill that child.
|
||||
kill(-child_pid, SIGKILL);
|
||||
}
|
||||
{
|
||||
// After a few gentle tries, really kill that child.
|
||||
kill(-child_pid, SIGKILL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -370,7 +370,7 @@ exec_with_timeout(const char* cmd)
|
|||
alarm_on = 0;
|
||||
|
||||
if (w == -1)
|
||||
error(2, errno, "error during wait()");
|
||||
error(2, errno, "error during wait()");
|
||||
|
||||
alarm(0);
|
||||
}
|
||||
|
|
@ -424,7 +424,7 @@ static int parse_opt_trans(int key, char* arg, struct argp_state*)
|
|||
timeout = to_pos_int(arg);
|
||||
#if !ENABLE_TIMEOUT
|
||||
std::cerr << "warning: setting a timeout is not supported "
|
||||
<< "on your platform" << std::endl;
|
||||
<< "on your platform" << std::endl;
|
||||
#endif
|
||||
break;
|
||||
case OPT_LIST:
|
||||
|
|
@ -437,4 +437,4 @@ static int parse_opt_trans(int key, char* arg, struct argp_state*)
|
|||
}
|
||||
|
||||
const struct argp trans_argp = { options, parse_opt_trans, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr };
|
||||
nullptr, nullptr, nullptr };
|
||||
|
|
|
|||
|
|
@ -89,9 +89,9 @@ public:
|
|||
using spot::formater::has;
|
||||
|
||||
translator_runner(spot::bdd_dict_ptr dict,
|
||||
// whether we accept the absence of output
|
||||
// specifier
|
||||
bool no_output_allowed = false);
|
||||
// whether we accept the absence of output
|
||||
// specifier
|
||||
bool no_output_allowed = false);
|
||||
void string_to_tmp(std::string& str, unsigned n, std::string& tmpname);
|
||||
const std::string& formula() const;
|
||||
void round_formula(spot::formula f, unsigned serial);
|
||||
|
|
|
|||
|
|
@ -89,9 +89,9 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case 'x':
|
||||
{
|
||||
const char* opt = extra_options.parse_options(arg);
|
||||
if (opt)
|
||||
error(2, 0, "failed to parse --options near '%s'", opt);
|
||||
const char* opt = extra_options.parse_options(arg);
|
||||
if (opt)
|
||||
error(2, 0, "failed to parse --options near '%s'", opt);
|
||||
}
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
|
|
@ -125,7 +125,7 @@ namespace
|
|||
|
||||
int
|
||||
process_automaton(const spot::const_parsed_aut_ptr& haut,
|
||||
const char* filename)
|
||||
const char* filename)
|
||||
{
|
||||
spot::stopwatch sw;
|
||||
sw.start();
|
||||
|
|
@ -151,19 +151,19 @@ namespace
|
|||
auto hp = spot::automaton_stream_parser(filename, opt_parse);
|
||||
int err = 0;
|
||||
while (!abort_run)
|
||||
{
|
||||
auto haut = hp.parse(spot::make_bdd_dict());
|
||||
if (!haut->aut && haut->errors.empty())
|
||||
break;
|
||||
if (haut->format_errors(std::cerr))
|
||||
err = 2;
|
||||
if (!haut->aut)
|
||||
error(2, 0, "failed to read automaton from %s", filename);
|
||||
else if (haut->aborted)
|
||||
err = std::max(err, aborted(haut, filename));
|
||||
else
|
||||
{
|
||||
auto haut = hp.parse(spot::make_bdd_dict());
|
||||
if (!haut->aut && haut->errors.empty())
|
||||
break;
|
||||
if (haut->format_errors(std::cerr))
|
||||
err = 2;
|
||||
if (!haut->aut)
|
||||
error(2, 0, "failed to read automaton from %s", filename);
|
||||
else if (haut->aborted)
|
||||
err = std::max(err, aborted(haut, filename));
|
||||
else
|
||||
process_automaton(haut, filename);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
};
|
||||
|
|
@ -175,7 +175,7 @@ main(int argc, char** argv)
|
|||
setup(argv);
|
||||
|
||||
const argp ap = { options, parse_opt, "[FILENAMES...]",
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
|
||||
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
|
||||
exit(err);
|
||||
|
|
@ -192,7 +192,7 @@ main(int argc, char** argv)
|
|||
{
|
||||
dstar_processor processor(post);
|
||||
if (processor.run())
|
||||
return 2;
|
||||
return 2;
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
|
|
|
|||
116
bin/genltl.cc
116
bin/genltl.cc
|
|
@ -43,8 +43,8 @@
|
|||
// @InProceedings{gastin.01.cav,
|
||||
// author = {Paul Gastin and Denis Oddoux},
|
||||
// title = {Fast {LTL} to {B\"u}chi Automata Translation},
|
||||
// booktitle = {Proceedings of the 13th International Conference on
|
||||
// Computer Aided Verification (CAV'01)},
|
||||
// booktitle = {Proceedings of the 13th International Conference on
|
||||
// Computer Aided Verification (CAV'01)},
|
||||
// pages = {53--65},
|
||||
// year = 2001,
|
||||
// editor = {G. Berry and H. Comon and A. Finkel},
|
||||
|
|
@ -58,7 +58,7 @@
|
|||
// author = {Kristin Y. Rozier and Moshe Y. Vardi},
|
||||
// title = {LTL Satisfiability Checking},
|
||||
// booktitle = {Proceedings of the 12th International SPIN Workshop on
|
||||
// Model Checking of Software (SPIN'07)},
|
||||
// Model Checking of Software (SPIN'07)},
|
||||
// pages = {149--167},
|
||||
// year = {2007},
|
||||
// volume = {4595},
|
||||
|
|
@ -294,9 +294,9 @@ E_n(std::string name, int n)
|
|||
p << name << n;
|
||||
formula f = formula::ap(p.str());
|
||||
if (result)
|
||||
result = And_(f, result);
|
||||
result = And_(f, result);
|
||||
else
|
||||
result = f;
|
||||
result = f;
|
||||
result = F_(result);
|
||||
}
|
||||
return result;
|
||||
|
|
@ -314,9 +314,9 @@ phi_n(std::string name, int n)
|
|||
for (; n > 0; --n)
|
||||
{
|
||||
if (result)
|
||||
result = And_(p, X_(result));
|
||||
result = And_(p, X_(result));
|
||||
else
|
||||
result = p;
|
||||
result = p;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -339,14 +339,14 @@ phi_prime_n(std::string name, int n)
|
|||
for (; n > 0; --n)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
p = X_(p);
|
||||
result = And_(result, p);
|
||||
}
|
||||
{
|
||||
p = X_(p);
|
||||
result = And_(result, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = p;
|
||||
}
|
||||
{
|
||||
result = p;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -377,9 +377,9 @@ GF_n(std::string name, int n, bool conj = true)
|
|||
formula f = G_(F_(formula::ap(p.str())));
|
||||
|
||||
if (result)
|
||||
result = formula::multop(o, {f, result});
|
||||
result = formula::multop(o, {f, result});
|
||||
else
|
||||
result = f;
|
||||
result = f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -403,9 +403,9 @@ FG_n(std::string name, int n, bool conj = false)
|
|||
formula f = F_(G_(formula::ap(p.str())));
|
||||
|
||||
if (result)
|
||||
result = formula::multop(o, {f, result});
|
||||
result = formula::multop(o, {f, result});
|
||||
else
|
||||
result = f;
|
||||
result = f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -426,11 +426,11 @@ bin_n(std::string name, int n, op o, bool right_assoc = false)
|
|||
p << name << (right_assoc ? (n + 1 - i) : i);
|
||||
formula f = formula::ap(p.str());
|
||||
if (!result)
|
||||
result = f;
|
||||
result = f;
|
||||
else if (right_assoc)
|
||||
result = formula::binop(o, f, result);
|
||||
result = formula::binop(o, f, result);
|
||||
else
|
||||
result = formula::binop(o, result, f);
|
||||
result = formula::binop(o, result, f);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -464,9 +464,9 @@ R_n(std::string name, int n)
|
|||
formula f = Or_(gf, fg);
|
||||
|
||||
if (result)
|
||||
result = And_(f, result);
|
||||
result = And_(f, result);
|
||||
else
|
||||
result = f;
|
||||
result = f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -501,9 +501,9 @@ Q_n(std::string name, int n)
|
|||
f = Or_(f, g);
|
||||
|
||||
if (result)
|
||||
result = And_(f, result);
|
||||
result = And_(f, result);
|
||||
else
|
||||
result = f;
|
||||
result = f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -527,9 +527,9 @@ combunop_n(std::string name, int n, op o, bool conj = false)
|
|||
formula f = formula::unop(o, formula::ap(p.str()));
|
||||
|
||||
if (result)
|
||||
result = formula::multop(cop, {f, result});
|
||||
result = formula::multop(cop, {f, result});
|
||||
else
|
||||
result = f;
|
||||
result = f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -575,7 +575,7 @@ ltl_counter(std::string bit, std::string marker, int n, bool linear)
|
|||
// G(m -> X(!m)&XX(!m)&XXX(m)) [if n = 3]
|
||||
std::vector<formula> v(n);
|
||||
for (int i = 0; i + 1 < n; ++i)
|
||||
v[i] = X_n(neg_m, i + 1);
|
||||
v[i] = X_n(neg_m, i + 1);
|
||||
v[n - 1] = X_n(m, n);
|
||||
res[0] = And_(m, G_(Implies_(m, formula::And(std::move(v)))));
|
||||
}
|
||||
|
|
@ -584,7 +584,7 @@ ltl_counter(std::string bit, std::string marker, int n, bool linear)
|
|||
// G(m -> X(!m & X(!m X(m)))) [if n = 3]
|
||||
formula p = m;
|
||||
for (int i = n - 1; i > 0; --i)
|
||||
p = And_(neg_m, X_(p));
|
||||
p = And_(neg_m, X_(p));
|
||||
res[0] = And_(m, G_(Implies_(m, X_(p))));
|
||||
}
|
||||
|
||||
|
|
@ -594,7 +594,7 @@ ltl_counter(std::string bit, std::string marker, int n, bool linear)
|
|||
// !b & X(!b) & XX(!b) [if n = 3]
|
||||
std::vector<formula> v2(n);
|
||||
for (int i = 0; i < n; ++i)
|
||||
v2[i] = X_n(neg_b, i);
|
||||
v2[i] = X_n(neg_b, i);
|
||||
res[1] = formula::And(std::move(v2));
|
||||
}
|
||||
else
|
||||
|
|
@ -602,7 +602,7 @@ ltl_counter(std::string bit, std::string marker, int n, bool linear)
|
|||
// !b & X(!b & X(!b)) [if n = 3]
|
||||
formula p = neg_b;
|
||||
for (int i = n - 1; i > 0; --i)
|
||||
p = And_(neg_b, X_(p));
|
||||
p = And_(neg_b, X_(p));
|
||||
res[1] = p;
|
||||
}
|
||||
|
||||
|
|
@ -613,26 +613,26 @@ ltl_counter(std::string bit, std::string marker, int n, bool linear)
|
|||
formula Xnm1_b = X_n(b, n - 1);
|
||||
formula Xn_b = X_(Xnm1_b);
|
||||
res[2] = G_(Implies_(And_(m, neg_b),
|
||||
AndX_(Xnm1_b, U_(And_(Not_(m), Equiv_(b, Xn_b)), m))));
|
||||
AndX_(Xnm1_b, U_(And_(Not_(m), Equiv_(b, Xn_b)), m))));
|
||||
|
||||
// From the least significant bit to the first 0, all the bits
|
||||
// are flipped on the next value. Remaining bits are identical.
|
||||
formula Xnm1_negb = X_n(neg_b, n - 1);
|
||||
formula Xn_negb = X_(Xnm1_negb);
|
||||
res[3] = G_(Implies_(And_(m, b),
|
||||
AndX_(Xnm1_negb,
|
||||
U_(And_(And_(b, neg_m), Xn_negb),
|
||||
Or_(m, And_(And_(neg_m, neg_b),
|
||||
AndX_(Xnm1_b,
|
||||
U_(And_(neg_m,
|
||||
Equiv_(b, Xn_b)),
|
||||
m))))))));
|
||||
AndX_(Xnm1_negb,
|
||||
U_(And_(And_(b, neg_m), Xn_negb),
|
||||
Or_(m, And_(And_(neg_m, neg_b),
|
||||
AndX_(Xnm1_b,
|
||||
U_(And_(neg_m,
|
||||
Equiv_(b, Xn_b)),
|
||||
m))))))));
|
||||
return formula::And(std::move(res));
|
||||
}
|
||||
|
||||
static formula
|
||||
ltl_counter_carry(std::string bit, std::string marker,
|
||||
std::string carry, int n, bool linear)
|
||||
std::string carry, int n, bool linear)
|
||||
{
|
||||
formula b = formula::ap(bit);
|
||||
formula neg_b = Not_(b);
|
||||
|
|
@ -650,7 +650,7 @@ ltl_counter_carry(std::string bit, std::string marker,
|
|||
// G(m -> X(!m)&XX(!m)&XXX(m)) [if n = 3]
|
||||
std::vector<formula> v(n);
|
||||
for (int i = 0; i + 1 < n; ++i)
|
||||
v[i] = X_n(neg_m, i + 1);
|
||||
v[i] = X_n(neg_m, i + 1);
|
||||
v[n - 1] = X_n(m, n);
|
||||
res[0] = And_(m, G_(Implies_(m, formula::And(std::move(v)))));
|
||||
}
|
||||
|
|
@ -659,7 +659,7 @@ ltl_counter_carry(std::string bit, std::string marker,
|
|||
// G(m -> X(!m & X(!m X(m)))) [if n = 3]
|
||||
formula p = m;
|
||||
for (int i = n - 1; i > 0; --i)
|
||||
p = And_(neg_m, X_(p));
|
||||
p = And_(neg_m, X_(p));
|
||||
res[0] = And_(m, G_(Implies_(m, X_(p))));
|
||||
}
|
||||
|
||||
|
|
@ -669,7 +669,7 @@ ltl_counter_carry(std::string bit, std::string marker,
|
|||
// !b & X(!b) & XX(!b) [if n = 3]
|
||||
std::vector<formula> v2(n);
|
||||
for (int i = 0; i < n; ++i)
|
||||
v2[i] = X_n(neg_b, i);
|
||||
v2[i] = X_n(neg_b, i);
|
||||
res[1] = formula::And(std::move(v2));
|
||||
}
|
||||
else
|
||||
|
|
@ -677,7 +677,7 @@ ltl_counter_carry(std::string bit, std::string marker,
|
|||
// !b & X(!b & X(!b)) [if n = 3]
|
||||
formula p = neg_b;
|
||||
for (int i = n - 1; i > 0; --i)
|
||||
p = And_(neg_b, X_(p));
|
||||
p = And_(neg_b, X_(p));
|
||||
res[1] = p;
|
||||
}
|
||||
|
||||
|
|
@ -694,24 +694,24 @@ ltl_counter_carry(std::string bit, std::string marker,
|
|||
{
|
||||
// If there's no carry, then all of the bits stay the same n steps later.
|
||||
res[4] = G_(Implies_(And_(neg_c, X_(neg_m)),
|
||||
And_(X_(Not_(c)), Equiv_(X_(b), X_(Xn_b)))));
|
||||
And_(X_(Not_(c)), Equiv_(X_(b), X_(Xn_b)))));
|
||||
|
||||
// If there's a carry, then add one: flip the bits of b and
|
||||
// adjust the carry.
|
||||
res[5] = G_(Implies_(c, And_(Implies_(X_(neg_b),
|
||||
And_(X_(neg_c), X_(Xn_b))),
|
||||
Implies_(X_(b),
|
||||
And_(X_(c), X_(Xn_negb))))));
|
||||
And_(X_(neg_c), X_(Xn_b))),
|
||||
Implies_(X_(b),
|
||||
And_(X_(c), X_(Xn_negb))))));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there's no carry, then all of the bits stay the same n steps later.
|
||||
res[4] = G_(Implies_(And_(neg_c, X_(neg_m)),
|
||||
X_(And_(Not_(c), Equiv_(b, Xn_b)))));
|
||||
X_(And_(Not_(c), Equiv_(b, Xn_b)))));
|
||||
// If there's a carry, then add one: flip the bits of b and
|
||||
// adjust the carry.
|
||||
res[5] = G_(Implies_(c, X_(And_(Implies_(neg_b, And_(neg_c, Xn_b)),
|
||||
Implies_(b, And_(c, Xn_negb))))));
|
||||
Implies_(b, And_(c, Xn_negb))))));
|
||||
}
|
||||
return formula::And(std::move(res));
|
||||
}
|
||||
|
|
@ -804,12 +804,12 @@ run_jobs()
|
|||
int inc = (j.range.max < j.range.min) ? -1 : 1;
|
||||
int n = j.range.min;
|
||||
for (;;)
|
||||
{
|
||||
output_pattern(j.pattern, n);
|
||||
if (n == j.range.max)
|
||||
break;
|
||||
n += inc;
|
||||
}
|
||||
{
|
||||
output_pattern(j.pattern, n);
|
||||
if (n == j.range.max)
|
||||
break;
|
||||
n += inc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -820,14 +820,14 @@ main(int argc, char** argv)
|
|||
setup(argv);
|
||||
|
||||
const argp ap = { options, parse_opt, nullptr, argp_program_doc,
|
||||
children, nullptr, nullptr };
|
||||
children, nullptr, nullptr };
|
||||
|
||||
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
|
||||
exit(err);
|
||||
|
||||
if (jobs.empty())
|
||||
error(1, 0, "Nothing to do. Try '%s --help' for more information.",
|
||||
program_name);
|
||||
program_name);
|
||||
|
||||
run_jobs();
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -90,9 +90,9 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case 'x':
|
||||
{
|
||||
const char* opt = extra_options.parse_options(arg);
|
||||
if (opt)
|
||||
error(2, 0, "failed to parse --options near '%s'", opt);
|
||||
const char* opt = extra_options.parse_options(arg);
|
||||
if (opt)
|
||||
error(2, 0, "failed to parse --options near '%s'", opt);
|
||||
}
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
|
|
@ -122,19 +122,19 @@ namespace
|
|||
|
||||
int
|
||||
process_formula(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
{
|
||||
// This should not happen, because the parser we use can only
|
||||
// read PSL/LTL formula, but since our formula type can
|
||||
// represent more than PSL formula, let's make this
|
||||
// future-proof.
|
||||
if (!f.is_psl_formula())
|
||||
{
|
||||
std::string s = spot::str_psl(f);
|
||||
error_at_line(2, 0, filename, linenum,
|
||||
"formula '%s' is not an LTL or PSL formula",
|
||||
s.c_str());
|
||||
}
|
||||
{
|
||||
std::string s = spot::str_psl(f);
|
||||
error_at_line(2, 0, filename, linenum,
|
||||
"formula '%s' is not an LTL or PSL formula",
|
||||
s.c_str());
|
||||
}
|
||||
|
||||
spot::stopwatch sw;
|
||||
sw.start();
|
||||
|
|
@ -142,7 +142,7 @@ namespace
|
|||
const double translation_time = sw.stop();
|
||||
|
||||
printer.print(aut, f, filename, linenum, translation_time, nullptr,
|
||||
prefix, suffix);
|
||||
prefix, suffix);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
|
@ -157,7 +157,7 @@ main(int argc, char** argv)
|
|||
setup(argv);
|
||||
|
||||
const argp ap = { options, parse_opt, "[FORMULA...]",
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
|
||||
simplification_level = 3;
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ main(int argc, char** argv)
|
|||
|
||||
if (jobs.empty())
|
||||
error(2, 0, "No formula to translate? Run '%s --help' for usage.",
|
||||
program_name);
|
||||
program_name);
|
||||
|
||||
spot::translator trans(&extra_options);
|
||||
trans.set_pref(pref | comp | sbacc | unambig);
|
||||
|
|
@ -177,7 +177,7 @@ main(int argc, char** argv)
|
|||
{
|
||||
trans_processor processor(trans);
|
||||
if (processor.run())
|
||||
return 2;
|
||||
return 2;
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -119,9 +119,9 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case 'x':
|
||||
{
|
||||
const char* opt = extra_options.parse_options(arg);
|
||||
if (opt)
|
||||
error(2, 0, "failed to parse --options near '%s'", opt);
|
||||
const char* opt = extra_options.parse_options(arg);
|
||||
if (opt)
|
||||
error(2, 0, "failed to parse --options near '%s'", opt);
|
||||
}
|
||||
break;
|
||||
case OPT_TGTA:
|
||||
|
|
@ -171,7 +171,7 @@ namespace
|
|||
|
||||
int
|
||||
process_formula(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
{
|
||||
auto aut = trans.run(&f);
|
||||
|
||||
|
|
@ -180,33 +180,33 @@ namespace
|
|||
// represent more than PSL formula, let's make this
|
||||
// future-proof.
|
||||
if (!f.is_psl_formula())
|
||||
{
|
||||
std::string s = spot::str_psl(f);
|
||||
error_at_line(2, 0, filename, linenum,
|
||||
"formula '%s' is not an LTL or PSL formula",
|
||||
s.c_str());
|
||||
}
|
||||
{
|
||||
std::string s = spot::str_psl(f);
|
||||
error_at_line(2, 0, filename, linenum,
|
||||
"formula '%s' is not an LTL or PSL formula",
|
||||
s.c_str());
|
||||
}
|
||||
|
||||
bdd ap_set = atomic_prop_collect_as_bdd(f, aut);
|
||||
|
||||
if (ta_type != TGTA)
|
||||
{
|
||||
auto testing_automaton =
|
||||
tgba_to_ta(aut, ap_set, type == spot::postprocessor::BA,
|
||||
opt_with_artificial_initial_state,
|
||||
opt_single_pass_emptiness_check,
|
||||
opt_with_artificial_livelock);
|
||||
if (level != spot::postprocessor::Low)
|
||||
testing_automaton = spot::minimize_ta(testing_automaton);
|
||||
spot::print_dot(std::cout, testing_automaton);
|
||||
}
|
||||
{
|
||||
auto testing_automaton =
|
||||
tgba_to_ta(aut, ap_set, type == spot::postprocessor::BA,
|
||||
opt_with_artificial_initial_state,
|
||||
opt_single_pass_emptiness_check,
|
||||
opt_with_artificial_livelock);
|
||||
if (level != spot::postprocessor::Low)
|
||||
testing_automaton = spot::minimize_ta(testing_automaton);
|
||||
spot::print_dot(std::cout, testing_automaton);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tgta = tgba_to_tgta(aut, ap_set);
|
||||
if (level != spot::postprocessor::Low)
|
||||
tgta = spot::minimize_tgta(tgta);
|
||||
spot::print_dot(std::cout, tgta->get_ta());
|
||||
}
|
||||
{
|
||||
auto tgta = tgba_to_tgta(aut, ap_set);
|
||||
if (level != spot::postprocessor::Low)
|
||||
tgta = spot::minimize_tgta(tgta);
|
||||
spot::print_dot(std::cout, tgta->get_ta());
|
||||
}
|
||||
flush_cout();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -219,7 +219,7 @@ main(int argc, char** argv)
|
|||
setup(argv);
|
||||
|
||||
const argp ap = { options, parse_opt, "[FORMULA...]",
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
|
||||
simplification_level = 3;
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ main(int argc, char** argv)
|
|||
|
||||
if (jobs.empty())
|
||||
error(2, 0, "No formula to translate? Run '%s --help' for usage.",
|
||||
program_name);
|
||||
program_name);
|
||||
|
||||
spot::translator trans(&extra_options);
|
||||
trans.set_pref(pref | comp | sbacc);
|
||||
|
|
|
|||
1540
bin/ltlcross.cc
1540
bin/ltlcross.cc
File diff suppressed because it is too large
Load diff
168
bin/ltldo.cc
168
bin/ltldo.cc
|
|
@ -151,57 +151,57 @@ namespace
|
|||
|
||||
spot::twa_graph_ptr res = nullptr;
|
||||
if (timed_out)
|
||||
{
|
||||
problem = false; // A timeout is considered benign
|
||||
std::cerr << "warning: timeout during execution of command \""
|
||||
<< cmd << "\"\n";
|
||||
++timeout_count;
|
||||
}
|
||||
{
|
||||
problem = false; // A timeout is considered benign
|
||||
std::cerr << "warning: timeout during execution of command \""
|
||||
<< cmd << "\"\n";
|
||||
++timeout_count;
|
||||
}
|
||||
else if (WIFSIGNALED(es))
|
||||
{
|
||||
problem = true;
|
||||
es = WTERMSIG(es);
|
||||
std::cerr << "error: execution of command \"" << cmd
|
||||
<< "\" terminated by signal " << es << ".\n";
|
||||
}
|
||||
{
|
||||
problem = true;
|
||||
es = WTERMSIG(es);
|
||||
std::cerr << "error: execution of command \"" << cmd
|
||||
<< "\" terminated by signal " << es << ".\n";
|
||||
}
|
||||
else if (WIFEXITED(es) && WEXITSTATUS(es) != 0)
|
||||
{
|
||||
problem = true;
|
||||
es = WEXITSTATUS(es);
|
||||
std::cerr << "error: execution of command \"" << cmd
|
||||
<< "\" returned exit code " << es << ".\n";
|
||||
}
|
||||
{
|
||||
problem = true;
|
||||
es = WEXITSTATUS(es);
|
||||
std::cerr << "error: execution of command \"" << cmd
|
||||
<< "\" returned exit code " << es << ".\n";
|
||||
}
|
||||
else if (output.val())
|
||||
{
|
||||
problem = false;
|
||||
auto aut = spot::parse_aut(output.val()->name(), dict,
|
||||
spot::default_environment::instance(),
|
||||
opt_parse);
|
||||
if (!aut->errors.empty())
|
||||
{
|
||||
problem = true;
|
||||
std::cerr << "error: failed to parse the automaton "
|
||||
"produced by \"" << cmd << "\".\n";
|
||||
aut->format_errors(std::cerr);
|
||||
res = nullptr;
|
||||
}
|
||||
else if (aut->aborted)
|
||||
{
|
||||
problem = true;
|
||||
std::cerr << "error: command \"" << cmd
|
||||
<< "\" aborted its output.\n";
|
||||
res = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = aut->aut;
|
||||
}
|
||||
}
|
||||
else // No automaton output
|
||||
{
|
||||
problem = false;
|
||||
res = nullptr;
|
||||
}
|
||||
{
|
||||
problem = false;
|
||||
auto aut = spot::parse_aut(output.val()->name(), dict,
|
||||
spot::default_environment::instance(),
|
||||
opt_parse);
|
||||
if (!aut->errors.empty())
|
||||
{
|
||||
problem = true;
|
||||
std::cerr << "error: failed to parse the automaton "
|
||||
"produced by \"" << cmd << "\".\n";
|
||||
aut->format_errors(std::cerr);
|
||||
res = nullptr;
|
||||
}
|
||||
else if (aut->aborted)
|
||||
{
|
||||
problem = true;
|
||||
std::cerr << "error: command \"" << cmd
|
||||
<< "\" aborted its output.\n";
|
||||
res = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = aut->aut;
|
||||
}
|
||||
}
|
||||
else // No automaton output
|
||||
{
|
||||
problem = false;
|
||||
res = nullptr;
|
||||
}
|
||||
|
||||
output.cleanup();
|
||||
return res;
|
||||
|
|
@ -234,18 +234,18 @@ namespace
|
|||
|
||||
int
|
||||
process_string(const std::string& input,
|
||||
const char* filename,
|
||||
int linenum)
|
||||
const char* filename,
|
||||
int linenum)
|
||||
{
|
||||
spot::parsed_formula pf = parse_formula(input);
|
||||
|
||||
if (!pf.f || !pf.errors.empty())
|
||||
{
|
||||
if (filename)
|
||||
error_at_line(0, 0, filename, linenum, "parse error:");
|
||||
pf.format_errors(std::cerr);
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
if (filename)
|
||||
error_at_line(0, 0, filename, linenum, "parse error:");
|
||||
pf.format_errors(std::cerr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inputf = input;
|
||||
process_formula(pf.f, filename, linenum);
|
||||
|
|
@ -255,43 +255,43 @@ namespace
|
|||
|
||||
int
|
||||
process_formula(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
{
|
||||
std::unique_ptr<spot::relabeling_map> relmap;
|
||||
|
||||
// If atomic propositions are incompatible with one of the
|
||||
// output, relabel the formula.
|
||||
if ((!f.has_lbt_atomic_props() &&
|
||||
(runner.has('l') || runner.has('L') || runner.has('T')))
|
||||
|| (!f.has_spin_atomic_props() &&
|
||||
(runner.has('s') || runner.has('S'))))
|
||||
{
|
||||
relmap.reset(new spot::relabeling_map);
|
||||
f = spot::relabel(f, spot::Pnn, relmap.get());
|
||||
}
|
||||
(runner.has('l') || runner.has('L') || runner.has('T')))
|
||||
|| (!f.has_spin_atomic_props() &&
|
||||
(runner.has('s') || runner.has('S'))))
|
||||
{
|
||||
relmap.reset(new spot::relabeling_map);
|
||||
f = spot::relabel(f, spot::Pnn, relmap.get());
|
||||
}
|
||||
|
||||
static unsigned round = 1;
|
||||
runner.round_formula(f, round);
|
||||
|
||||
unsigned ts = translators.size();
|
||||
for (unsigned t = 0; t < ts; ++t)
|
||||
{
|
||||
bool problem;
|
||||
double translation_time;
|
||||
auto aut = runner.translate(t, problem, translation_time);
|
||||
if (problem)
|
||||
error_at_line(2, 0, filename, linenum, "aborting here");
|
||||
if (aut)
|
||||
{
|
||||
if (relmap)
|
||||
relabel_here(aut, relmap.get());
|
||||
aut = post.run(aut, f);
|
||||
cmdname = translators[t].name;
|
||||
roundval = round;
|
||||
printer.print(aut, f, filename, linenum, translation_time,
|
||||
nullptr, prefix, suffix);
|
||||
};
|
||||
}
|
||||
{
|
||||
bool problem;
|
||||
double translation_time;
|
||||
auto aut = runner.translate(t, problem, translation_time);
|
||||
if (problem)
|
||||
error_at_line(2, 0, filename, linenum, "aborting here");
|
||||
if (aut)
|
||||
{
|
||||
if (relmap)
|
||||
relabel_here(aut, relmap.get());
|
||||
aut = post.run(aut, f);
|
||||
cmdname = translators[t].name;
|
||||
roundval = round;
|
||||
printer.print(aut, f, filename, linenum, translation_time,
|
||||
nullptr, prefix, suffix);
|
||||
};
|
||||
}
|
||||
spot::cleanup_tmpfiles();
|
||||
++round;
|
||||
return 0;
|
||||
|
|
@ -305,7 +305,7 @@ main(int argc, char** argv)
|
|||
setup(argv);
|
||||
|
||||
const argp ap = { options, parse_opt, "[COMMANDFMT...]",
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
|
||||
// Disable post-processing as much as possible by default.
|
||||
level = spot::postprocessor::Low;
|
||||
|
|
@ -319,7 +319,7 @@ main(int argc, char** argv)
|
|||
|
||||
if (translators.empty())
|
||||
error(2, 0, "No translator to run? Run '%s --help' for usage.",
|
||||
program_name);
|
||||
program_name);
|
||||
|
||||
setup_sig_handler();
|
||||
|
||||
|
|
@ -332,7 +332,7 @@ main(int argc, char** argv)
|
|||
{
|
||||
processor p(post);
|
||||
if (p.run())
|
||||
return 2;
|
||||
return 2;
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
|
|
|
|||
260
bin/ltlfilt.cc
260
bin/ltlfilt.cc
|
|
@ -348,10 +348,10 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case OPT_EQUIVALENT_TO:
|
||||
{
|
||||
if (opt->equivalent_to)
|
||||
error(2, 0, "only one --equivalent-to option can be given");
|
||||
opt->equivalent_to = parse_formula_arg(arg);
|
||||
break;
|
||||
if (opt->equivalent_to)
|
||||
error(2, 0, "only one --equivalent-to option can be given");
|
||||
opt->equivalent_to = parse_formula_arg(arg);
|
||||
break;
|
||||
}
|
||||
case OPT_EXCLUSIVE_AP:
|
||||
opt->excl_ap.add_group(arg);
|
||||
|
|
@ -364,17 +364,17 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case OPT_IMPLIED_BY:
|
||||
{
|
||||
spot::formula i = parse_formula_arg(arg);
|
||||
// a→c∧b→c ≡ (a∨b)→c
|
||||
opt->implied_by = spot::formula::Or({opt->implied_by, i});
|
||||
break;
|
||||
spot::formula i = parse_formula_arg(arg);
|
||||
// a→c∧b→c ≡ (a∨b)→c
|
||||
opt->implied_by = spot::formula::Or({opt->implied_by, i});
|
||||
break;
|
||||
}
|
||||
case OPT_IMPLY:
|
||||
{
|
||||
// a→b∧a→c ≡ a→(b∧c)
|
||||
spot::formula i = parse_formula_arg(arg);
|
||||
opt->imply = spot::formula::And({opt->imply, i});
|
||||
break;
|
||||
// a→b∧a→c ≡ a→(b∧c)
|
||||
spot::formula i = parse_formula_arg(arg);
|
||||
opt->imply = spot::formula::And({opt->imply, i});
|
||||
break;
|
||||
}
|
||||
case OPT_LTL:
|
||||
ltl = true;
|
||||
|
|
@ -392,13 +392,13 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
case OPT_RELABEL_BOOL:
|
||||
relabeling = (key == OPT_RELABEL_BOOL ? BseRelabeling : ApRelabeling);
|
||||
if (!arg || !strncasecmp(arg, "abc", 6))
|
||||
style = spot::Abc;
|
||||
style = spot::Abc;
|
||||
else if (!strncasecmp(arg, "pnn", 4))
|
||||
style = spot::Pnn;
|
||||
style = spot::Pnn;
|
||||
else
|
||||
error(2, 0, "invalid argument for --relabel%s: '%s'",
|
||||
(key == OPT_RELABEL_BOOL ? "-bool" : ""),
|
||||
arg);
|
||||
error(2, 0, "invalid argument for --relabel%s: '%s'",
|
||||
(key == OPT_RELABEL_BOOL ? "-bool" : ""),
|
||||
arg);
|
||||
break;
|
||||
case OPT_REMOVE_WM:
|
||||
unabbreviate += "MW";
|
||||
|
|
@ -426,9 +426,9 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case OPT_UNABBREVIATE:
|
||||
if (arg)
|
||||
unabbreviate += arg;
|
||||
unabbreviate += arg;
|
||||
else
|
||||
unabbreviate += spot::default_unabbrev_string;
|
||||
unabbreviate += spot::default_unabbrev_string;
|
||||
break;
|
||||
case OPT_AP_N:
|
||||
ap_n = parse_range(arg, 0, std::numeric_limits<int>::max());
|
||||
|
|
@ -479,87 +479,87 @@ namespace
|
|||
|
||||
int
|
||||
process_string(const std::string& input,
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
{
|
||||
spot::parsed_formula pf = parse_formula(input);
|
||||
|
||||
if (!pf.f || !pf.errors.empty())
|
||||
{
|
||||
if (!ignore_errors)
|
||||
{
|
||||
if (filename)
|
||||
error_at_line(0, 0, filename, linenum, "parse error:");
|
||||
pf.format_errors(std::cerr);
|
||||
}
|
||||
{
|
||||
if (!ignore_errors)
|
||||
{
|
||||
if (filename)
|
||||
error_at_line(0, 0, filename, linenum, "parse error:");
|
||||
pf.format_errors(std::cerr);
|
||||
}
|
||||
|
||||
if (error_style == skip_errors)
|
||||
std::cout << input << '\n';
|
||||
else
|
||||
assert(error_style == drop_errors);
|
||||
check_cout();
|
||||
return !ignore_errors;
|
||||
}
|
||||
if (error_style == skip_errors)
|
||||
std::cout << input << '\n';
|
||||
else
|
||||
assert(error_style == drop_errors);
|
||||
check_cout();
|
||||
return !ignore_errors;
|
||||
}
|
||||
try
|
||||
{
|
||||
return process_formula(pf.f, filename, linenum);
|
||||
}
|
||||
{
|
||||
return process_formula(pf.f, filename, linenum);
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
error_at_line(2, 0, filename, linenum, "%s", e.what());
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
{
|
||||
error_at_line(2, 0, filename, linenum, "%s", e.what());
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
process_formula(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
{
|
||||
if (opt_max_count >= 0 && match_count >= opt_max_count)
|
||||
{
|
||||
abort_run = true;
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
abort_run = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (negate)
|
||||
f = spot::formula::Not(f);
|
||||
f = spot::formula::Not(f);
|
||||
|
||||
if (remove_x)
|
||||
{
|
||||
// If simplification are enabled, we do them before and after.
|
||||
if (simplification_level)
|
||||
f = simpl.simplify(f);
|
||||
f = spot::remove_x(f);
|
||||
}
|
||||
{
|
||||
// If simplification are enabled, we do them before and after.
|
||||
if (simplification_level)
|
||||
f = simpl.simplify(f);
|
||||
f = spot::remove_x(f);
|
||||
}
|
||||
|
||||
if (simplification_level || boolean_to_isop)
|
||||
f = simpl.simplify(f);
|
||||
f = simpl.simplify(f);
|
||||
|
||||
if (nnf)
|
||||
f = simpl.negative_normal_form(f);
|
||||
f = simpl.negative_normal_form(f);
|
||||
|
||||
switch (relabeling)
|
||||
{
|
||||
case ApRelabeling:
|
||||
{
|
||||
relmap.clear();
|
||||
f = spot::relabel(f, style, &relmap);
|
||||
break;
|
||||
}
|
||||
case BseRelabeling:
|
||||
{
|
||||
relmap.clear();
|
||||
f = spot::relabel_bse(f, style, &relmap);
|
||||
break;
|
||||
}
|
||||
case NoRelabeling:
|
||||
break;
|
||||
}
|
||||
{
|
||||
case ApRelabeling:
|
||||
{
|
||||
relmap.clear();
|
||||
f = spot::relabel(f, style, &relmap);
|
||||
break;
|
||||
}
|
||||
case BseRelabeling:
|
||||
{
|
||||
relmap.clear();
|
||||
f = spot::relabel_bse(f, style, &relmap);
|
||||
break;
|
||||
}
|
||||
case NoRelabeling:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!unabbreviate.empty())
|
||||
f = spot::unabbreviate(f, unabbreviate.c_str());
|
||||
f = spot::unabbreviate(f, unabbreviate.c_str());
|
||||
|
||||
if (!opt->excl_ap.empty())
|
||||
f = opt->excl_ap.constrain(f);
|
||||
f = opt->excl_ap.constrain(f);
|
||||
|
||||
bool matched = true;
|
||||
|
||||
|
|
@ -575,32 +575,32 @@ namespace
|
|||
matched &= !syntactic_persistence || f.is_syntactic_persistence();
|
||||
matched &= !syntactic_si || f.is_syntactic_stutter_invariant();
|
||||
if (matched && (ap_n.min > 0 || ap_n.max >= 0))
|
||||
{
|
||||
auto s = atomic_prop_collect(f);
|
||||
int n = s->size();
|
||||
delete s;
|
||||
matched &= (ap_n.min <= 0) || (n >= ap_n.min);
|
||||
matched &= (ap_n.max < 0) || (n <= ap_n.max);
|
||||
}
|
||||
{
|
||||
auto s = atomic_prop_collect(f);
|
||||
int n = s->size();
|
||||
delete s;
|
||||
matched &= (ap_n.min <= 0) || (n >= ap_n.min);
|
||||
matched &= (ap_n.max < 0) || (n <= ap_n.max);
|
||||
}
|
||||
|
||||
if (matched && (size.min > 0 || size.max >= 0))
|
||||
{
|
||||
int l = spot::length(f);
|
||||
matched &= (size.min <= 0) || (l >= size.min);
|
||||
matched &= (size.max < 0) || (l <= size.max);
|
||||
}
|
||||
{
|
||||
int l = spot::length(f);
|
||||
matched &= (size.min <= 0) || (l >= size.min);
|
||||
matched &= (size.max < 0) || (l <= size.max);
|
||||
}
|
||||
|
||||
if (matched && (bsize.min > 0 || bsize.max >= 0))
|
||||
{
|
||||
int l = spot::length_boolone(f);
|
||||
matched &= (bsize.min <= 0) || (l >= bsize.min);
|
||||
matched &= (bsize.max < 0) || (l <= bsize.max);
|
||||
}
|
||||
{
|
||||
int l = spot::length_boolone(f);
|
||||
matched &= (bsize.min <= 0) || (l >= bsize.min);
|
||||
matched &= (bsize.max < 0) || (l <= bsize.max);
|
||||
}
|
||||
|
||||
matched &= !opt->implied_by || simpl.implication(opt->implied_by, f);
|
||||
matched &= !opt->imply || simpl.implication(f, opt->imply);
|
||||
matched &= !opt->equivalent_to
|
||||
|| simpl.are_equivalent(f, opt->equivalent_to);
|
||||
|| simpl.are_equivalent(f, opt->equivalent_to);
|
||||
matched &= !stutter_insensitive || spot::is_stutter_invariant(f);
|
||||
|
||||
// Match obligations and subclasses using WDBA minimization.
|
||||
|
|
@ -608,46 +608,46 @@ namespace
|
|||
// have to compute it on formulas that have been discarded for
|
||||
// other reasons.
|
||||
if (matched && obligation)
|
||||
{
|
||||
auto aut = ltl_to_tgba_fm(f, simpl.get_dict());
|
||||
auto min = minimize_obligation(aut, f);
|
||||
assert(min);
|
||||
if (aut == min)
|
||||
{
|
||||
// Not an obligation
|
||||
matched = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
matched &= !guarantee || is_terminal_automaton(min);
|
||||
matched &= !safety || is_safety_mwdba(min);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto aut = ltl_to_tgba_fm(f, simpl.get_dict());
|
||||
auto min = minimize_obligation(aut, f);
|
||||
assert(min);
|
||||
if (aut == min)
|
||||
{
|
||||
// Not an obligation
|
||||
matched = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
matched &= !guarantee || is_terminal_automaton(min);
|
||||
matched &= !safety || is_safety_mwdba(min);
|
||||
}
|
||||
}
|
||||
|
||||
matched ^= invert;
|
||||
|
||||
if (unique && !unique_set.insert(f).second)
|
||||
matched = false;
|
||||
matched = false;
|
||||
|
||||
if (matched)
|
||||
{
|
||||
if (opt->output_define
|
||||
&& output_format != count_output
|
||||
&& output_format != quiet_output)
|
||||
{
|
||||
// Sort the formulas alphabetically.
|
||||
std::map<std::string, spot::formula> m;
|
||||
for (auto& p: relmap)
|
||||
m.emplace(str_psl(p.first), p.second);
|
||||
for (auto& p: m)
|
||||
stream_formula(opt->output_define->ostream()
|
||||
<< "#define " << p.first << " (",
|
||||
p.second, filename, linenum) << ")\n";
|
||||
}
|
||||
one_match = true;
|
||||
output_formula_checked(f, filename, linenum, prefix, suffix);
|
||||
++match_count;
|
||||
}
|
||||
{
|
||||
if (opt->output_define
|
||||
&& output_format != count_output
|
||||
&& output_format != quiet_output)
|
||||
{
|
||||
// Sort the formulas alphabetically.
|
||||
std::map<std::string, spot::formula> m;
|
||||
for (auto& p: relmap)
|
||||
m.emplace(str_psl(p.first), p.second);
|
||||
for (auto& p: m)
|
||||
stream_formula(opt->output_define->ostream()
|
||||
<< "#define " << p.first << " (",
|
||||
p.second, filename, linenum) << ")\n";
|
||||
}
|
||||
one_match = true;
|
||||
output_formula_checked(f, filename, linenum, prefix, suffix);
|
||||
++match_count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
|
@ -659,7 +659,7 @@ main(int argc, char** argv)
|
|||
setup(argv);
|
||||
|
||||
const argp ap = { options, parse_opt, "[FILENAME[/COL]...]",
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
argp_program_doc, children, nullptr, nullptr };
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -669,20 +669,20 @@ main(int argc, char** argv)
|
|||
opt = &o;
|
||||
|
||||
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
|
||||
exit(err);
|
||||
exit(err);
|
||||
|
||||
if (jobs.empty())
|
||||
jobs.emplace_back("-", 1);
|
||||
jobs.emplace_back("-", 1);
|
||||
|
||||
if (boolean_to_isop && simplification_level == 0)
|
||||
simplification_level = 1;
|
||||
simplification_level = 1;
|
||||
spot::tl_simplifier_options opt(simplification_level);
|
||||
opt.boolean_to_isop = boolean_to_isop;
|
||||
spot::tl_simplifier simpl(opt);
|
||||
|
||||
ltl_processor processor(simpl);
|
||||
if (processor.run())
|
||||
return 2;
|
||||
return 2;
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -113,12 +113,12 @@ namespace
|
|||
public:
|
||||
int
|
||||
process_formula(spot::formula f, const char* filename = nullptr,
|
||||
int linenum = 0)
|
||||
int linenum = 0)
|
||||
{
|
||||
auto mutations =
|
||||
spot::mutate(f, mut_opts, max_output, mutation_nb, opt_sort);
|
||||
spot::mutate(f, mut_opts, max_output, mutation_nb, opt_sort);
|
||||
for (auto g: mutations)
|
||||
output_formula_checked(g, filename, linenum, prefix, suffix);
|
||||
output_formula_checked(g, filename, linenum, prefix, suffix);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
|
@ -182,7 +182,7 @@ main(int argc, char* argv[])
|
|||
setup(argv);
|
||||
|
||||
const argp ap = { options, parse_opt, "[FILENAME[/COL]...]", argp_program_doc,
|
||||
children, nullptr, nullptr };
|
||||
children, nullptr, nullptr };
|
||||
|
||||
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
|
||||
exit(err);
|
||||
|
|
|
|||
198
bin/randaut.cc
198
bin/randaut.cc
|
|
@ -191,24 +191,24 @@ parse_opt(int key, char* arg, struct argp_state* as)
|
|||
case 'a':
|
||||
opt_acc_prob = to_float(arg);
|
||||
if (opt_acc_prob < 0.0 || opt_acc_prob > 1.0)
|
||||
error(2, 0, "probability of acceptance set membership "
|
||||
"should be between 0.0 and 1.0");
|
||||
error(2, 0, "probability of acceptance set membership "
|
||||
"should be between 0.0 and 1.0");
|
||||
break;
|
||||
case 'A':
|
||||
if (looks_like_a_range(arg))
|
||||
{
|
||||
opt_acc_sets = parse_range(arg);
|
||||
if (opt_acc_sets.min > opt_acc_sets.max)
|
||||
std::swap(opt_acc_sets.min, opt_acc_sets.max);
|
||||
if (opt_acc_sets.min < 0)
|
||||
error(2, 0, "number of acceptance sets should be positive");
|
||||
gba_wanted = true;
|
||||
}
|
||||
{
|
||||
opt_acc_sets = parse_range(arg);
|
||||
if (opt_acc_sets.min > opt_acc_sets.max)
|
||||
std::swap(opt_acc_sets.min, opt_acc_sets.max);
|
||||
if (opt_acc_sets.min < 0)
|
||||
error(2, 0, "number of acceptance sets should be positive");
|
||||
gba_wanted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
opt_acceptance = arg;
|
||||
generic_wanted = true;
|
||||
}
|
||||
{
|
||||
opt_acceptance = arg;
|
||||
generic_wanted = true;
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
ba_options();
|
||||
|
|
@ -217,7 +217,7 @@ parse_opt(int key, char* arg, struct argp_state* as)
|
|||
case 'e':
|
||||
opt_density = to_float(arg);
|
||||
if (opt_density < 0.0 || opt_density > 1.0)
|
||||
error(2, 0, "density should be between 0.0 and 1.0");
|
||||
error(2, 0, "density should be between 0.0 and 1.0");
|
||||
break;
|
||||
case 'D':
|
||||
opt_deterministic = true;
|
||||
|
|
@ -228,9 +228,9 @@ parse_opt(int key, char* arg, struct argp_state* as)
|
|||
case 'Q':
|
||||
opt_states = parse_range(arg);
|
||||
if (opt_states.min > opt_states.max)
|
||||
std::swap(opt_states.min, opt_states.max);
|
||||
std::swap(opt_states.min, opt_states.max);
|
||||
if (opt_states.min == 0)
|
||||
error(1, 0, "cannot build an automaton with 0 states");
|
||||
error(1, 0, "cannot build an automaton with 0 states");
|
||||
break;
|
||||
case 'S':
|
||||
opt_state_acc = true;
|
||||
|
|
@ -255,14 +255,14 @@ parse_opt(int key, char* arg, struct argp_state* as)
|
|||
// last non-option argument, and if aprops.empty() we know this
|
||||
// is the also the first one.
|
||||
if (opt->aprops.empty()
|
||||
&& as->argc == as->next && looks_like_a_range(arg))
|
||||
{
|
||||
ap_count_given = parse_range(arg);
|
||||
// Create the set once if the count is fixed.
|
||||
if (ap_count_given.min == ap_count_given.max)
|
||||
opt->aprops = spot::create_atomic_prop_set(ap_count_given.min);
|
||||
break;
|
||||
}
|
||||
&& as->argc == as->next && looks_like_a_range(arg))
|
||||
{
|
||||
ap_count_given = parse_range(arg);
|
||||
// Create the set once if the count is fixed.
|
||||
if (ap_count_given.min == ap_count_given.max)
|
||||
opt->aprops = spot::create_atomic_prop_set(ap_count_given.min);
|
||||
break;
|
||||
}
|
||||
opt->aprops.insert(spot::formula::ap(arg));
|
||||
break;
|
||||
|
||||
|
|
@ -281,7 +281,7 @@ main(int argc, char** argv)
|
|||
setup(argv);
|
||||
|
||||
const argp ap = { options, parse_opt, "N|PROP...", argp_program_doc,
|
||||
children, nullptr, nullptr };
|
||||
children, nullptr, nullptr };
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -291,43 +291,43 @@ main(int argc, char** argv)
|
|||
opt = &o;
|
||||
|
||||
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
|
||||
exit(err);
|
||||
exit(err);
|
||||
|
||||
// running 'randaut 0' is one way to generate automata using no
|
||||
// atomic propositions so do not complain in that case.
|
||||
if (opt->aprops.empty() && ap_count_given.max < 0)
|
||||
error(2, 0,
|
||||
"No atomic proposition supplied? Run '%s --help' for usage.",
|
||||
program_name);
|
||||
error(2, 0,
|
||||
"No atomic proposition supplied? Run '%s --help' for usage.",
|
||||
program_name);
|
||||
|
||||
if (generic_wanted && automaton_format == Spin)
|
||||
error(2, 0,
|
||||
"--spin implies --ba so should not be used with --acceptance");
|
||||
error(2, 0,
|
||||
"--spin implies --ba so should not be used with --acceptance");
|
||||
if (generic_wanted && ba_wanted)
|
||||
error(2, 0, "--acceptance and --ba may not be used together");
|
||||
error(2, 0, "--acceptance and --ba may not be used together");
|
||||
|
||||
if (automaton_format == Spin && opt_acc_sets.max > 1)
|
||||
error(2, 0, "--spin is incompatible with --acceptance=%d..%d",
|
||||
opt_acc_sets.min, opt_acc_sets.max);
|
||||
error(2, 0, "--spin is incompatible with --acceptance=%d..%d",
|
||||
opt_acc_sets.min, opt_acc_sets.max);
|
||||
if (ba_wanted && opt_acc_sets.min != 1 && opt_acc_sets.max != 1)
|
||||
error(2, 0, "--ba is incompatible with --acceptance=%d..%d",
|
||||
opt_acc_sets.min, opt_acc_sets.max);
|
||||
error(2, 0, "--ba is incompatible with --acceptance=%d..%d",
|
||||
opt_acc_sets.min, opt_acc_sets.max);
|
||||
if (ba_wanted && generic_wanted)
|
||||
error(2, 0,
|
||||
"--ba is incompatible with --acceptance=%s", opt_acceptance);
|
||||
error(2, 0,
|
||||
"--ba is incompatible with --acceptance=%s", opt_acceptance);
|
||||
|
||||
if (automaton_format == Spin)
|
||||
ba_options();
|
||||
ba_options();
|
||||
|
||||
if (opt_colored && opt_acc_sets.min == -1 && !generic_wanted)
|
||||
error(2, 0, "--colored requires at least one acceptance set; "
|
||||
"use --acceptance");
|
||||
error(2, 0, "--colored requires at least one acceptance set; "
|
||||
"use --acceptance");
|
||||
if (opt_colored && opt_acc_sets.min == 0)
|
||||
error(2, 0, "--colored requires at least one acceptance set; "
|
||||
"fix the range of --acceptance");
|
||||
error(2, 0, "--colored requires at least one acceptance set; "
|
||||
"fix the range of --acceptance");
|
||||
|
||||
if (opt_acc_sets.min == -1)
|
||||
opt_acc_sets.min = 0;
|
||||
opt_acc_sets.min = 0;
|
||||
|
||||
spot::srand(opt_seed);
|
||||
auto d = spot::make_bdd_dict();
|
||||
|
|
@ -340,70 +340,70 @@ main(int argc, char** argv)
|
|||
int automaton_num = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
spot::stopwatch sw;
|
||||
sw.start();
|
||||
{
|
||||
spot::stopwatch sw;
|
||||
sw.start();
|
||||
|
||||
if (ap_count_given.max > 0
|
||||
&& ap_count_given.min != ap_count_given.max)
|
||||
{
|
||||
int c = spot::rrand(ap_count_given.min, ap_count_given.max);
|
||||
opt->aprops = spot::create_atomic_prop_set(c);
|
||||
}
|
||||
if (ap_count_given.max > 0
|
||||
&& ap_count_given.min != ap_count_given.max)
|
||||
{
|
||||
int c = spot::rrand(ap_count_given.min, ap_count_given.max);
|
||||
opt->aprops = spot::create_atomic_prop_set(c);
|
||||
}
|
||||
|
||||
int size = opt_states.min;
|
||||
if (size != opt_states.max)
|
||||
size = spot::rrand(size, opt_states.max);
|
||||
int size = opt_states.min;
|
||||
if (size != opt_states.max)
|
||||
size = spot::rrand(size, opt_states.max);
|
||||
|
||||
int accs = opt_acc_sets.min;
|
||||
if (accs != opt_acc_sets.max)
|
||||
accs = spot::rrand(accs, opt_acc_sets.max);
|
||||
int accs = opt_acc_sets.min;
|
||||
if (accs != opt_acc_sets.max)
|
||||
accs = spot::rrand(accs, opt_acc_sets.max);
|
||||
|
||||
spot::acc_cond::acc_code code;
|
||||
if (opt_acceptance)
|
||||
{
|
||||
code = spot::acc_cond::acc_code(opt_acceptance);
|
||||
accs = code.used_sets().max_set();
|
||||
if (opt_colored && accs == 0)
|
||||
error(2, 0, "--colored requires at least one acceptance set; "
|
||||
"fix the range of --acceptance");
|
||||
}
|
||||
spot::acc_cond::acc_code code;
|
||||
if (opt_acceptance)
|
||||
{
|
||||
code = spot::acc_cond::acc_code(opt_acceptance);
|
||||
accs = code.used_sets().max_set();
|
||||
if (opt_colored && accs == 0)
|
||||
error(2, 0, "--colored requires at least one acceptance set; "
|
||||
"fix the range of --acceptance");
|
||||
}
|
||||
|
||||
auto aut =
|
||||
spot::random_graph(size, opt_density, &opt->aprops, d,
|
||||
accs, opt_acc_prob, 0.5,
|
||||
opt_deterministic, opt_state_acc,
|
||||
opt_colored);
|
||||
auto aut =
|
||||
spot::random_graph(size, opt_density, &opt->aprops, d,
|
||||
accs, opt_acc_prob, 0.5,
|
||||
opt_deterministic, opt_state_acc,
|
||||
opt_colored);
|
||||
|
||||
if (opt_acceptance)
|
||||
aut->set_acceptance(accs, code);
|
||||
if (opt_acceptance)
|
||||
aut->set_acceptance(accs, code);
|
||||
|
||||
if (opt_uniq)
|
||||
{
|
||||
auto tmp = spot::canonicalize
|
||||
(make_twa_graph(aut, spot::twa::prop_set::all()));
|
||||
std::vector<tr_t> trans(tmp->edge_vector().begin() + 1,
|
||||
tmp->edge_vector().end());
|
||||
if (!opt_uniq->emplace(trans).second)
|
||||
{
|
||||
--trials;
|
||||
if (trials == 0)
|
||||
error(2, 0, "failed to generate a new unique automaton"
|
||||
" after %d trials", max_trials);
|
||||
continue;
|
||||
}
|
||||
trials = max_trials;
|
||||
}
|
||||
if (opt_uniq)
|
||||
{
|
||||
auto tmp = spot::canonicalize
|
||||
(make_twa_graph(aut, spot::twa::prop_set::all()));
|
||||
std::vector<tr_t> trans(tmp->edge_vector().begin() + 1,
|
||||
tmp->edge_vector().end());
|
||||
if (!opt_uniq->emplace(trans).second)
|
||||
{
|
||||
--trials;
|
||||
if (trials == 0)
|
||||
error(2, 0, "failed to generate a new unique automaton"
|
||||
" after %d trials", max_trials);
|
||||
continue;
|
||||
}
|
||||
trials = max_trials;
|
||||
}
|
||||
|
||||
auto runtime = sw.stop();
|
||||
auto runtime = sw.stop();
|
||||
|
||||
printer.print(aut, nullptr,
|
||||
opt_seed_str, automaton_num, runtime, nullptr);
|
||||
printer.print(aut, nullptr,
|
||||
opt_seed_str, automaton_num, runtime, nullptr);
|
||||
|
||||
++automaton_num;
|
||||
if (opt_automata > 0 && automaton_num >= opt_automata)
|
||||
break;
|
||||
}
|
||||
++automaton_num;
|
||||
if (opt_automata > 0 && automaton_num >= opt_automata)
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
|
|
|
|||
144
bin/randltl.cc
144
bin/randltl.cc
|
|
@ -197,7 +197,7 @@ parse_opt(int key, char* arg, struct argp_state* as)
|
|||
case OPT_TREE_SIZE:
|
||||
opt_tree_size = parse_range(arg);
|
||||
if (opt_tree_size.min > opt_tree_size.max)
|
||||
std::swap(opt_tree_size.min, opt_tree_size.max);
|
||||
std::swap(opt_tree_size.min, opt_tree_size.max);
|
||||
break;
|
||||
case OPT_WF:
|
||||
opt_wf = true;
|
||||
|
|
@ -211,16 +211,16 @@ parse_opt(int key, char* arg, struct argp_state* as)
|
|||
// last non-option argument, and if aprops.empty() we know this
|
||||
// is the also the first one.
|
||||
if (opt->aprops.empty() && as->argc == as->next)
|
||||
{
|
||||
char* endptr;
|
||||
int res = strtol(arg, &endptr, 10);
|
||||
if (!*endptr && res >= 0) // arg is a number
|
||||
{
|
||||
ap_count_given = true;
|
||||
opt->aprops = spot::create_atomic_prop_set(res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
char* endptr;
|
||||
int res = strtol(arg, &endptr, 10);
|
||||
if (!*endptr && res >= 0) // arg is a number
|
||||
{
|
||||
ap_count_given = true;
|
||||
opt->aprops = spot::create_atomic_prop_set(res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
opt->aprops.insert(spot::default_environment::instance().require(arg));
|
||||
break;
|
||||
default:
|
||||
|
|
@ -235,7 +235,7 @@ main(int argc, char** argv)
|
|||
setup(argv);
|
||||
|
||||
const argp ap = { options, parse_opt, "N|PROP...", argp_program_doc,
|
||||
children, nullptr, nullptr };
|
||||
children, nullptr, nullptr };
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -245,78 +245,78 @@ main(int argc, char** argv)
|
|||
opt = &o;
|
||||
|
||||
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
|
||||
exit(err);
|
||||
exit(err);
|
||||
|
||||
// running 'randltl 0' is one way to generate formulas using no
|
||||
// atomic propositions so do not complain in that case.
|
||||
if (opt->aprops.empty() && !ap_count_given)
|
||||
error(2, 0, "No atomic proposition supplied? "
|
||||
"Run '%s --help' for usage.", program_name);
|
||||
error(2, 0, "No atomic proposition supplied? "
|
||||
"Run '%s --help' for usage.", program_name);
|
||||
|
||||
spot::srand(opt_seed);
|
||||
|
||||
spot::randltlgenerator rg
|
||||
(opt->aprops,
|
||||
[&] (){
|
||||
spot::option_map opts;
|
||||
opts.set("output", output);
|
||||
opts.set("tree_size_min", opt_tree_size.min);
|
||||
opts.set("tree_size_max", opt_tree_size.max);
|
||||
opts.set("wf", opt_wf);
|
||||
opts.set("seed", opt_seed);
|
||||
opts.set("simplification_level", simplification_level);
|
||||
return opts;
|
||||
}(), opt_pL, opt_pS, opt_pB);
|
||||
(opt->aprops,
|
||||
[&] (){
|
||||
spot::option_map opts;
|
||||
opts.set("output", output);
|
||||
opts.set("tree_size_min", opt_tree_size.min);
|
||||
opts.set("tree_size_max", opt_tree_size.max);
|
||||
opts.set("wf", opt_wf);
|
||||
opts.set("seed", opt_seed);
|
||||
opts.set("simplification_level", simplification_level);
|
||||
return opts;
|
||||
}(), opt_pL, opt_pS, opt_pB);
|
||||
|
||||
if (opt_dump_priorities)
|
||||
{
|
||||
switch (output)
|
||||
{
|
||||
case OUTPUTLTL:
|
||||
std::cout <<
|
||||
"Use --ltl-priorities to set the following LTL priorities:\n";
|
||||
rg.dump_ltl_priorities(std::cout);
|
||||
break;
|
||||
case OUTPUTBOOL:
|
||||
std::cout <<
|
||||
"Use --boolean-priorities to set the following Boolean "
|
||||
"formula priorities:\n";
|
||||
rg.dump_bool_priorities(std::cout);
|
||||
break;
|
||||
case OUTPUTPSL:
|
||||
std::cout <<
|
||||
"Use --ltl-priorities to set the following LTL priorities:\n";
|
||||
rg.dump_psl_priorities(std::cout);
|
||||
// Fall through.
|
||||
case OUTPUTSERE:
|
||||
std::cout <<
|
||||
"Use --sere-priorities to set the following SERE priorities:\n";
|
||||
rg.dump_sere_priorities(std::cout);
|
||||
std::cout <<
|
||||
"Use --boolean-priorities to set the following Boolean "
|
||||
"formula priorities:\n";
|
||||
rg.dump_sere_bool_priorities(std::cout);
|
||||
break;
|
||||
default:
|
||||
error(2, 0, "internal error: unknown type of output");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
{
|
||||
switch (output)
|
||||
{
|
||||
case OUTPUTLTL:
|
||||
std::cout <<
|
||||
"Use --ltl-priorities to set the following LTL priorities:\n";
|
||||
rg.dump_ltl_priorities(std::cout);
|
||||
break;
|
||||
case OUTPUTBOOL:
|
||||
std::cout <<
|
||||
"Use --boolean-priorities to set the following Boolean "
|
||||
"formula priorities:\n";
|
||||
rg.dump_bool_priorities(std::cout);
|
||||
break;
|
||||
case OUTPUTPSL:
|
||||
std::cout <<
|
||||
"Use --ltl-priorities to set the following LTL priorities:\n";
|
||||
rg.dump_psl_priorities(std::cout);
|
||||
// Fall through.
|
||||
case OUTPUTSERE:
|
||||
std::cout <<
|
||||
"Use --sere-priorities to set the following SERE priorities:\n";
|
||||
rg.dump_sere_priorities(std::cout);
|
||||
std::cout <<
|
||||
"Use --boolean-priorities to set the following Boolean "
|
||||
"formula priorities:\n";
|
||||
rg.dump_sere_bool_priorities(std::cout);
|
||||
break;
|
||||
default:
|
||||
error(2, 0, "internal error: unknown type of output");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
while (opt_formulas < 0 || opt_formulas--)
|
||||
{
|
||||
static int count = 0;
|
||||
spot::formula f = rg.next();
|
||||
if (!f)
|
||||
{
|
||||
error(2, 0, "failed to generate a new unique formula after %d " \
|
||||
"trials", MAX_TRIALS);
|
||||
}
|
||||
else
|
||||
{
|
||||
output_formula_checked(f, nullptr, ++count);
|
||||
}
|
||||
};
|
||||
{
|
||||
static int count = 0;
|
||||
spot::formula f = rg.next();
|
||||
if (!f)
|
||||
{
|
||||
error(2, 0, "failed to generate a new unique formula after %d " \
|
||||
"trials", MAX_TRIALS);
|
||||
}
|
||||
else
|
||||
{
|
||||
output_formula_checked(f, nullptr, ++count);
|
||||
}
|
||||
};
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ Enabled by default.") },
|
|||
if the TGBA is not already deterministic. Doing so will degeneralize \
|
||||
the automaton. This is disabled by default, unless sat-minimize is set.") },
|
||||
{ DOC("sat-minimize",
|
||||
"Set to 1 to enable SAT-based minimization of deterministic \
|
||||
"Set to 1 to enable SAT-based minimization of deterministic \
|
||||
TGBA: it starts with the number of states of the input, and iteratively \
|
||||
tries to find a deterministic TGBA with one less state. Set to 2 to perform \
|
||||
a binary search instead. Disabled (0) by default. The sat solver to use \
|
||||
|
|
@ -123,7 +123,7 @@ set; this can be changed with the sat-acc option, or of course by using -B \
|
|||
to construct a Büchi automaton. Enabling SAT-based minimization will \
|
||||
also enable tba-det.") },
|
||||
{ DOC("sat-states",
|
||||
"When this is set to some positive integer, the SAT-based \
|
||||
"When this is set to some positive integer, the SAT-based \
|
||||
minimization will attempt to construct a TGBA with the given number of \
|
||||
states. It may however return an automaton with less states if some of \
|
||||
these are unreachable or useless. Setting sat-states automatically \
|
||||
|
|
@ -131,13 +131,13 @@ enables sat-minimize, but no iteration is performed. If no equivalent \
|
|||
automaton could be constructed with the given number of states, the original \
|
||||
automaton is returned.") },
|
||||
{ DOC("sat-acc",
|
||||
"When this is set to some positive integer, the SAT-based will \
|
||||
"When this is set to some positive integer, the SAT-based will \
|
||||
attempt to construct a TGBA with the given number of acceptance sets. \
|
||||
states. It may however return an automaton with less acceptance sets if \
|
||||
some of these are useless. Setting sat-acc automatically \
|
||||
sets sat-minimize to 1 if not set differently.") },
|
||||
{ DOC("state-based",
|
||||
"Set to 1 to instruct the SAT-minimization procedure to produce \
|
||||
"Set to 1 to instruct the SAT-minimization procedure to produce \
|
||||
a TGBA where all outgoing transition of a state have the same acceptance \
|
||||
sets. By default this is only enabled when option -B is used.") },
|
||||
{ nullptr, 0, nullptr, 0, nullptr, 0 }
|
||||
|
|
@ -155,13 +155,13 @@ main(int argc, char** argv)
|
|||
setup(argv);
|
||||
|
||||
const argp ap = { options, nullptr, nullptr, argp_program_doc, children,
|
||||
nullptr, nullptr };
|
||||
nullptr, nullptr };
|
||||
|
||||
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
|
||||
exit(err);
|
||||
|
||||
std::cerr << "This binary serves no purpose other than generating"
|
||||
<< " the spot-x.7 manpage.\n";
|
||||
<< " the spot-x.7 manpage.\n";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace spot
|
|||
struct first_is_base_of<Of, Arg1, Args...>
|
||||
{
|
||||
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
|
||||
|
||||
|
|
@ -65,11 +65,11 @@ namespace spot
|
|||
|
||||
#ifndef SWIG
|
||||
template <typename... Args,
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<boxed_label, Args...>::value>::type>
|
||||
boxed_label(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Data, Args...>::value)
|
||||
: label{std::forward<Args>(args)...}
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<boxed_label, Args...>::value>::type>
|
||||
boxed_label(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Data, Args...>::value)
|
||||
: label{std::forward<Args>(args)...}
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
@ -77,23 +77,23 @@ namespace spot
|
|||
// if Data is a POD type, G++ 4.8.2 wants default values for all
|
||||
// label fields unless we define this default constructor here.
|
||||
explicit boxed_label()
|
||||
noexcept(std::is_nothrow_constructible<Data>::value)
|
||||
noexcept(std::is_nothrow_constructible<Data>::value)
|
||||
{
|
||||
}
|
||||
|
||||
Data& data()
|
||||
{
|
||||
return label;
|
||||
return label;
|
||||
}
|
||||
|
||||
const Data& data() const
|
||||
{
|
||||
return label;
|
||||
return label;
|
||||
}
|
||||
|
||||
bool operator<(const boxed_label& other) const
|
||||
{
|
||||
return label < other.label;
|
||||
return label < other.label;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -103,12 +103,12 @@ namespace spot
|
|||
typedef std::tuple<> data_t;
|
||||
std::tuple<>& data()
|
||||
{
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const std::tuple<>& data() const
|
||||
{
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -120,11 +120,11 @@ namespace spot
|
|||
|
||||
#ifndef SWIG
|
||||
template <typename... Args,
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<boxed_label, Args...>::value>::type>
|
||||
boxed_label(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Data, Args...>::value)
|
||||
: Data{std::forward<Args>(args)...}
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<boxed_label, Args...>::value>::type>
|
||||
boxed_label(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Data, Args...>::value)
|
||||
: Data{std::forward<Args>(args)...}
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
@ -132,18 +132,18 @@ namespace spot
|
|||
// if Data is a POD type, G++ 4.8.2 wants default values for all
|
||||
// label fields unless we define this default constructor here.
|
||||
explicit boxed_label()
|
||||
noexcept(std::is_nothrow_constructible<Data>::value)
|
||||
noexcept(std::is_nothrow_constructible<Data>::value)
|
||||
{
|
||||
}
|
||||
|
||||
Data& data()
|
||||
{
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Data& data() const
|
||||
{
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -158,15 +158,15 @@ namespace spot
|
|||
struct SPOT_API distate_storage final: public State_Data
|
||||
{
|
||||
Edge succ = 0; // First outgoing edge (used when iterating)
|
||||
Edge succ_tail = 0; // Last outgoing edge (used for
|
||||
// appending new edges)
|
||||
Edge succ_tail = 0; // Last outgoing edge (used for
|
||||
// appending new edges)
|
||||
#ifndef SWIG
|
||||
template <typename... Args,
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<distate_storage, Args...>::value>::type>
|
||||
typename = typename std::enable_if<
|
||||
!first_is_base_of<distate_storage, Args...>::value>::type>
|
||||
distate_storage(Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<State_Data, Args...>::value)
|
||||
: State_Data{std::forward<Args>(args)...}
|
||||
noexcept(std::is_nothrow_constructible<State_Data, Args...>::value)
|
||||
: State_Data{std::forward<Args>(args)...}
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
@ -179,47 +179,47 @@ namespace spot
|
|||
// Again two implementation: one with label, and one without.
|
||||
|
||||
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
|
||||
{
|
||||
typedef Edge edge;
|
||||
|
||||
StateOut dst; // destination
|
||||
Edge next_succ; // next outgoing edge with same
|
||||
// source, or 0
|
||||
StateIn src; // source
|
||||
StateOut dst; // destination
|
||||
Edge next_succ; // next outgoing edge with same
|
||||
// source, or 0
|
||||
StateIn src; // source
|
||||
|
||||
explicit edge_storage()
|
||||
noexcept(std::is_nothrow_constructible<Edge_Data>::value)
|
||||
: Edge_Data{}
|
||||
noexcept(std::is_nothrow_constructible<Edge_Data>::value)
|
||||
: Edge_Data{}
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef SWIG
|
||||
template <typename... Args>
|
||||
edge_storage(StateOut dst, Edge next_succ,
|
||||
StateIn src, Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Edge_Data, Args...>::value
|
||||
&& std::is_nothrow_constructible<StateOut, StateOut>::value
|
||||
&& std::is_nothrow_constructible<Edge, Edge>::value)
|
||||
: Edge_Data{std::forward<Args>(args)...},
|
||||
dst(dst), next_succ(next_succ), src(src)
|
||||
StateIn src, Args&&... args)
|
||||
noexcept(std::is_nothrow_constructible<Edge_Data, Args...>::value
|
||||
&& std::is_nothrow_constructible<StateOut, StateOut>::value
|
||||
&& std::is_nothrow_constructible<Edge, Edge>::value)
|
||||
: Edge_Data{std::forward<Args>(args)...},
|
||||
dst(dst), next_succ(next_succ), src(src)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator<(const edge_storage& other) const
|
||||
{
|
||||
if (src < other.src)
|
||||
return true;
|
||||
if (src > other.src)
|
||||
return false;
|
||||
// This might be costly if the destination is a vector
|
||||
if (dst < other.dst)
|
||||
return true;
|
||||
if (dst > other.dst)
|
||||
return false;
|
||||
return this->data() < other.data();
|
||||
if (src < other.src)
|
||||
return true;
|
||||
if (src > other.src)
|
||||
return false;
|
||||
// This might be costly if the destination is a vector
|
||||
if (dst < other.dst)
|
||||
return true;
|
||||
if (dst > other.dst)
|
||||
return false;
|
||||
return this->data() < other.data();
|
||||
}
|
||||
|
||||
bool operator==(const edge_storage& other) const
|
||||
|
|
@ -241,86 +241,86 @@ namespace spot
|
|||
template <typename Graph>
|
||||
class SPOT_API edge_iterator: public
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
{
|
||||
typedef
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
super;
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
super;
|
||||
public:
|
||||
typedef typename Graph::edge edge;
|
||||
|
||||
edge_iterator() noexcept
|
||||
: g_(nullptr), t_(0)
|
||||
: g_(nullptr), t_(0)
|
||||
{
|
||||
}
|
||||
|
||||
edge_iterator(Graph* g, edge t) noexcept
|
||||
: g_(g), t_(t)
|
||||
: g_(g), t_(t)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(edge_iterator o) const
|
||||
{
|
||||
return t_ == o.t_;
|
||||
return t_ == o.t_;
|
||||
}
|
||||
|
||||
bool operator!=(edge_iterator o) const
|
||||
{
|
||||
return t_ != o.t_;
|
||||
return t_ != o.t_;
|
||||
}
|
||||
|
||||
typename super::reference
|
||||
operator*()
|
||||
{
|
||||
return g_->edge_storage(t_);
|
||||
return g_->edge_storage(t_);
|
||||
}
|
||||
|
||||
const typename super::reference
|
||||
operator*() const
|
||||
{
|
||||
return g_->edge_storage(t_);
|
||||
return g_->edge_storage(t_);
|
||||
}
|
||||
|
||||
typename super::pointer
|
||||
operator->()
|
||||
{
|
||||
return &g_->edge_storage(t_);
|
||||
return &g_->edge_storage(t_);
|
||||
}
|
||||
|
||||
const typename super::pointer
|
||||
operator->() const
|
||||
{
|
||||
return &g_->edge_storage(t_);
|
||||
return &g_->edge_storage(t_);
|
||||
}
|
||||
|
||||
edge_iterator operator++()
|
||||
{
|
||||
t_ = operator*().next_succ;
|
||||
return *this;
|
||||
t_ = operator*().next_succ;
|
||||
return *this;
|
||||
}
|
||||
|
||||
edge_iterator operator++(int)
|
||||
{
|
||||
edge_iterator ti = *this;
|
||||
t_ = operator*().next_succ;
|
||||
return ti;
|
||||
edge_iterator ti = *this;
|
||||
t_ = operator*().next_succ;
|
||||
return ti;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return t_;
|
||||
return t_;
|
||||
}
|
||||
|
||||
edge trans() const
|
||||
{
|
||||
return t_;
|
||||
return t_;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -337,52 +337,52 @@ namespace spot
|
|||
typedef typename Graph::edge edge;
|
||||
|
||||
killer_edge_iterator(Graph* g, edge t, state_storage_t& src) noexcept
|
||||
: super(g, t), src_(src), prev_(0)
|
||||
: super(g, t), src_(src), prev_(0)
|
||||
{
|
||||
}
|
||||
|
||||
killer_edge_iterator operator++()
|
||||
{
|
||||
prev_ = this->t_;
|
||||
this->t_ = this->operator*().next_succ;
|
||||
return *this;
|
||||
prev_ = this->t_;
|
||||
this->t_ = this->operator*().next_succ;
|
||||
return *this;
|
||||
}
|
||||
|
||||
killer_edge_iterator operator++(int)
|
||||
{
|
||||
killer_edge_iterator ti = *this;
|
||||
++*this;
|
||||
return ti;
|
||||
killer_edge_iterator ti = *this;
|
||||
++*this;
|
||||
return ti;
|
||||
}
|
||||
|
||||
// Erase the current edge and advance the iterator.
|
||||
void erase()
|
||||
{
|
||||
edge next = this->operator*().next_succ;
|
||||
edge next = this->operator*().next_succ;
|
||||
|
||||
// Update source state and previous edges
|
||||
if (prev_)
|
||||
{
|
||||
this->g_->edge_storage(prev_).next_succ = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (src_.succ == this->t_)
|
||||
src_.succ = next;
|
||||
}
|
||||
if (src_.succ_tail == this->t_)
|
||||
{
|
||||
src_.succ_tail = prev_;
|
||||
assert(next == 0);
|
||||
}
|
||||
// Update source state and previous edges
|
||||
if (prev_)
|
||||
{
|
||||
this->g_->edge_storage(prev_).next_succ = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (src_.succ == this->t_)
|
||||
src_.succ = next;
|
||||
}
|
||||
if (src_.succ_tail == this->t_)
|
||||
{
|
||||
src_.succ_tail = prev_;
|
||||
assert(next == 0);
|
||||
}
|
||||
|
||||
// Erased edges have themselves as next_succ.
|
||||
this->operator*().next_succ = this->t_;
|
||||
// Erased edges have themselves as next_succ.
|
||||
this->operator*().next_succ = this->t_;
|
||||
|
||||
// Advance iterator to next edge.
|
||||
this->t_ = next;
|
||||
// Advance iterator to next edge.
|
||||
this->t_ = next;
|
||||
|
||||
++this->g_->killed_edge_;
|
||||
++this->g_->killed_edge_;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -403,23 +403,23 @@ namespace spot
|
|||
public:
|
||||
typedef typename Graph::edge edge;
|
||||
state_out(Graph* g, edge t) noexcept
|
||||
: g_(g), t_(t)
|
||||
: g_(g), t_(t)
|
||||
{
|
||||
}
|
||||
|
||||
edge_iterator<Graph> begin()
|
||||
{
|
||||
return {g_, t_};
|
||||
return {g_, t_};
|
||||
}
|
||||
|
||||
edge_iterator<Graph> end()
|
||||
{
|
||||
return {};
|
||||
return {};
|
||||
}
|
||||
|
||||
void recycle(edge t)
|
||||
{
|
||||
t_ = t;
|
||||
t_ = t;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -434,92 +434,92 @@ namespace spot
|
|||
template <typename Graph>
|
||||
class SPOT_API all_edge_iterator: public
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
{
|
||||
typedef
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
super;
|
||||
std::iterator<std::forward_iterator_tag,
|
||||
typename
|
||||
std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_storage_t,
|
||||
typename Graph::edge_storage_t>::type>
|
||||
super;
|
||||
|
||||
typedef typename std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_vector_t,
|
||||
typename Graph::edge_vector_t>::type
|
||||
tv_t;
|
||||
const typename Graph::edge_vector_t,
|
||||
typename Graph::edge_vector_t>::type
|
||||
tv_t;
|
||||
|
||||
unsigned t_;
|
||||
tv_t& tv_;
|
||||
|
||||
void skip_()
|
||||
{
|
||||
unsigned s = tv_.size();
|
||||
do
|
||||
++t_;
|
||||
while (t_ < s && tv_[t_].next_succ == t_);
|
||||
unsigned s = tv_.size();
|
||||
do
|
||||
++t_;
|
||||
while (t_ < s && tv_[t_].next_succ == t_);
|
||||
}
|
||||
|
||||
public:
|
||||
all_edge_iterator(unsigned pos, tv_t& tv) noexcept
|
||||
: t_(pos), tv_(tv)
|
||||
: t_(pos), tv_(tv)
|
||||
{
|
||||
skip_();
|
||||
skip_();
|
||||
}
|
||||
|
||||
all_edge_iterator(tv_t& tv) noexcept
|
||||
: t_(tv.size()), tv_(tv)
|
||||
: t_(tv.size()), tv_(tv)
|
||||
{
|
||||
}
|
||||
|
||||
all_edge_iterator& operator++()
|
||||
{
|
||||
skip_();
|
||||
return *this;
|
||||
skip_();
|
||||
return *this;
|
||||
}
|
||||
|
||||
all_edge_iterator operator++(int)
|
||||
{
|
||||
all_edge_iterator old = *this;
|
||||
++*this;
|
||||
return old;
|
||||
all_edge_iterator old = *this;
|
||||
++*this;
|
||||
return old;
|
||||
}
|
||||
|
||||
bool operator==(all_edge_iterator o) const
|
||||
{
|
||||
return t_ == o.t_;
|
||||
return t_ == o.t_;
|
||||
}
|
||||
|
||||
bool operator!=(all_edge_iterator o) const
|
||||
{
|
||||
return t_ != o.t_;
|
||||
return t_ != o.t_;
|
||||
}
|
||||
|
||||
typename super::reference
|
||||
operator*()
|
||||
{
|
||||
return tv_[t_];
|
||||
return tv_[t_];
|
||||
}
|
||||
|
||||
const typename super::reference
|
||||
operator*() const
|
||||
{
|
||||
return tv_[t_];
|
||||
return tv_[t_];
|
||||
}
|
||||
|
||||
const typename super::pointer
|
||||
operator->()
|
||||
{
|
||||
return &tv_[t_];
|
||||
return &tv_[t_];
|
||||
}
|
||||
|
||||
typename super::pointer
|
||||
operator->() const
|
||||
{
|
||||
return &tv_[t_];
|
||||
return &tv_[t_];
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -529,27 +529,27 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
typedef typename std::conditional<std::is_const<Graph>::value,
|
||||
const typename Graph::edge_vector_t,
|
||||
typename Graph::edge_vector_t>::type
|
||||
tv_t;
|
||||
const typename Graph::edge_vector_t,
|
||||
typename Graph::edge_vector_t>::type
|
||||
tv_t;
|
||||
typedef all_edge_iterator<Graph> iter_t;
|
||||
private:
|
||||
tv_t& tv_;
|
||||
public:
|
||||
|
||||
all_trans(tv_t& tv) noexcept
|
||||
: tv_(tv)
|
||||
: tv_(tv)
|
||||
{
|
||||
}
|
||||
|
||||
iter_t begin()
|
||||
{
|
||||
return {0, tv_};
|
||||
return {0, tv_};
|
||||
}
|
||||
|
||||
iter_t end()
|
||||
{
|
||||
return {tv_};
|
||||
return {tv_};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -586,14 +586,14 @@ namespace spot
|
|||
// The type of an output state (when seen from a edge)
|
||||
// depends on the kind of graph we build
|
||||
typedef typename std::conditional<Alternating,
|
||||
std::vector<state>,
|
||||
state>::type out_state;
|
||||
std::vector<state>,
|
||||
state>::type out_state;
|
||||
|
||||
typedef internal::distate_storage<edge,
|
||||
internal::boxed_label<State_Data>>
|
||||
internal::boxed_label<State_Data>>
|
||||
state_storage_t;
|
||||
typedef internal::edge_storage<state, out_state, edge,
|
||||
internal::boxed_label<Edge_Data>>
|
||||
internal::boxed_label<Edge_Data>>
|
||||
edge_storage_t;
|
||||
typedef std::vector<state_storage_t> state_vector;
|
||||
typedef std::vector<edge_storage_t> edge_vector_t;
|
||||
|
|
@ -614,7 +614,7 @@ namespace spot
|
|||
{
|
||||
states_.reserve(max_states);
|
||||
if (max_trans == 0)
|
||||
max_trans = max_states * 2;
|
||||
max_trans = max_states * 2;
|
||||
edges_.reserve(max_trans + 1);
|
||||
// Edge number 0 is not used, because we use this index
|
||||
// to mark the absence of a edge.
|
||||
|
|
@ -638,7 +638,7 @@ namespace spot
|
|||
// Erased edges have their next_succ pointing to
|
||||
// themselves.
|
||||
return (t < edges_.size() &&
|
||||
edges_[t].next_succ != t);
|
||||
edges_[t].next_succ != t);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
|
|
@ -655,7 +655,7 @@ namespace spot
|
|||
state s = states_.size();
|
||||
states_.reserve(s + n);
|
||||
while (n--)
|
||||
states_.emplace_back(std::forward<Args>(args)...);
|
||||
states_.emplace_back(std::forward<Args>(args)...);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
@ -730,9 +730,9 @@ namespace spot
|
|||
edge st = states_[src].succ_tail;
|
||||
assert(st < t || !st);
|
||||
if (!st)
|
||||
states_[src].succ = t;
|
||||
states_[src].succ = t;
|
||||
else
|
||||
edges_[st].next_succ = t;
|
||||
edges_[st].next_succ = t;
|
||||
states_[src].succ_tail = t;
|
||||
return t;
|
||||
}
|
||||
|
|
@ -836,19 +836,19 @@ namespace spot
|
|||
{
|
||||
unsigned tend = edges_.size();
|
||||
for (unsigned t = 1; t < tend; ++t)
|
||||
{
|
||||
o << 't' << t << ": (s"
|
||||
<< edges_[t].src << ", s"
|
||||
<< edges_[t].dst << ") t"
|
||||
<< edges_[t].next_succ << '\n';
|
||||
}
|
||||
{
|
||||
o << 't' << t << ": (s"
|
||||
<< edges_[t].src << ", s"
|
||||
<< edges_[t].dst << ") t"
|
||||
<< edges_[t].next_succ << '\n';
|
||||
}
|
||||
unsigned send = states_.size();
|
||||
for (unsigned s = 0; s < send; ++s)
|
||||
{
|
||||
o << 's' << s << ": t"
|
||||
<< states_[s].succ << " t"
|
||||
<< states_[s].succ_tail << '\n';
|
||||
}
|
||||
{
|
||||
o << 's' << s << ": t"
|
||||
<< states_[s].succ << " t"
|
||||
<< states_[s].succ_tail << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all dead edges. The edges_ vector is left
|
||||
|
|
@ -858,11 +858,11 @@ namespace spot
|
|||
void remove_dead_edges_()
|
||||
{
|
||||
if (killed_edge_ == 0)
|
||||
return;
|
||||
return;
|
||||
auto i = std::remove_if(edges_.begin() + 1, edges_.end(),
|
||||
[this](const edge_storage_t& t) {
|
||||
return this->is_dead_edge(t);
|
||||
});
|
||||
[this](const edge_storage_t& t) {
|
||||
return this->is_dead_edge(t);
|
||||
});
|
||||
edges_.erase(i, edges_.end());
|
||||
killed_edge_ = 0;
|
||||
}
|
||||
|
|
@ -885,38 +885,38 @@ namespace spot
|
|||
state last_src = -1U;
|
||||
edge tend = edges_.size();
|
||||
for (edge t = 1; t < tend; ++t)
|
||||
{
|
||||
state src = edges_[t].src;
|
||||
if (src != last_src)
|
||||
{
|
||||
states_[src].succ = t;
|
||||
if (last_src != -1U)
|
||||
{
|
||||
states_[last_src].succ_tail = t - 1;
|
||||
edges_[t - 1].next_succ = 0;
|
||||
}
|
||||
while (++last_src != src)
|
||||
{
|
||||
states_[last_src].succ = 0;
|
||||
states_[last_src].succ_tail = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
edges_[t - 1].next_succ = t;
|
||||
}
|
||||
}
|
||||
{
|
||||
state src = edges_[t].src;
|
||||
if (src != last_src)
|
||||
{
|
||||
states_[src].succ = t;
|
||||
if (last_src != -1U)
|
||||
{
|
||||
states_[last_src].succ_tail = t - 1;
|
||||
edges_[t - 1].next_succ = 0;
|
||||
}
|
||||
while (++last_src != src)
|
||||
{
|
||||
states_[last_src].succ = 0;
|
||||
states_[last_src].succ_tail = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
edges_[t - 1].next_succ = t;
|
||||
}
|
||||
}
|
||||
if (last_src != -1U)
|
||||
{
|
||||
states_[last_src].succ_tail = tend - 1;
|
||||
edges_[tend - 1].next_succ = 0;
|
||||
}
|
||||
{
|
||||
states_[last_src].succ_tail = tend - 1;
|
||||
edges_[tend - 1].next_succ = 0;
|
||||
}
|
||||
unsigned send = states_.size();
|
||||
while (++last_src != send)
|
||||
{
|
||||
states_[last_src].succ = 0;
|
||||
states_[last_src].succ_tail = 0;
|
||||
}
|
||||
{
|
||||
states_[last_src].succ = 0;
|
||||
states_[last_src].succ_tail = 0;
|
||||
}
|
||||
//std::cerr << "\nafter\n";
|
||||
//dump_storage(std::cerr);
|
||||
}
|
||||
|
|
@ -930,10 +930,10 @@ namespace spot
|
|||
assert(newst.size() == states_.size());
|
||||
unsigned tend = edges_.size();
|
||||
for (unsigned t = 1; t < tend; t++)
|
||||
{
|
||||
edges_[t].dst = newst[edges_[t].dst];
|
||||
edges_[t].src = newst[edges_[t].src];
|
||||
}
|
||||
{
|
||||
edges_[t].dst = newst[edges_[t].dst];
|
||||
edges_[t].src = newst[edges_[t].src];
|
||||
}
|
||||
}
|
||||
|
||||
void defrag_states(std::vector<unsigned>&& newst, unsigned used_states)
|
||||
|
|
@ -947,22 +947,22 @@ namespace spot
|
|||
// Shift all states in states_, as indicated by newst.
|
||||
unsigned send = states_.size();
|
||||
for (state s = 0; s < send; ++s)
|
||||
{
|
||||
state dst = newst[s];
|
||||
if (dst == s)
|
||||
continue;
|
||||
if (dst == -1U)
|
||||
{
|
||||
// This is an erased state. Mark all its edges as
|
||||
// dead (i.e., t.next_succ should point to t for each of
|
||||
// them).
|
||||
auto t = states_[s].succ;
|
||||
while (t)
|
||||
std::swap(t, edges_[t].next_succ);
|
||||
continue;
|
||||
}
|
||||
states_[dst] = std::move(states_[s]);
|
||||
}
|
||||
{
|
||||
state dst = newst[s];
|
||||
if (dst == s)
|
||||
continue;
|
||||
if (dst == -1U)
|
||||
{
|
||||
// This is an erased state. Mark all its edges as
|
||||
// dead (i.e., t.next_succ should point to t for each of
|
||||
// them).
|
||||
auto t = states_[s].succ;
|
||||
while (t)
|
||||
std::swap(t, edges_[t].next_succ);
|
||||
continue;
|
||||
}
|
||||
states_[dst] = std::move(states_[s]);
|
||||
}
|
||||
states_.resize(used_states);
|
||||
|
||||
// Shift all edges in edges_. The algorithm is
|
||||
|
|
@ -972,33 +972,33 @@ namespace spot
|
|||
std::vector<edge> newidx(tend);
|
||||
unsigned dest = 1;
|
||||
for (edge t = 1; t < tend; ++t)
|
||||
{
|
||||
if (is_dead_edge(t))
|
||||
continue;
|
||||
if (t != dest)
|
||||
edges_[dest] = std::move(edges_[t]);
|
||||
newidx[t] = dest;
|
||||
++dest;
|
||||
}
|
||||
{
|
||||
if (is_dead_edge(t))
|
||||
continue;
|
||||
if (t != dest)
|
||||
edges_[dest] = std::move(edges_[t]);
|
||||
newidx[t] = dest;
|
||||
++dest;
|
||||
}
|
||||
edges_.resize(dest);
|
||||
killed_edge_ = 0;
|
||||
|
||||
// Adjust next_succ and dst pointers in all edges.
|
||||
for (edge t = 1; t < dest; ++t)
|
||||
{
|
||||
auto& tr = edges_[t];
|
||||
tr.next_succ = newidx[tr.next_succ];
|
||||
tr.dst = newst[tr.dst];
|
||||
tr.src = newst[tr.src];
|
||||
assert(tr.dst != -1U);
|
||||
}
|
||||
{
|
||||
auto& tr = edges_[t];
|
||||
tr.next_succ = newidx[tr.next_succ];
|
||||
tr.dst = newst[tr.dst];
|
||||
tr.src = newst[tr.src];
|
||||
assert(tr.dst != -1U);
|
||||
}
|
||||
|
||||
// Adjust succ and succ_tails pointers in all states.
|
||||
for (auto& s: states_)
|
||||
{
|
||||
s.succ = newidx[s.succ];
|
||||
s.succ_tail = newidx[s.succ_tail];
|
||||
}
|
||||
{
|
||||
s.succ = newidx[s.succ];
|
||||
s.succ_tail = newidx[s.succ_tail];
|
||||
}
|
||||
|
||||
//std::cerr << "\nafter defrag\n";
|
||||
//dump_storage(std::cerr);
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@
|
|||
namespace spot
|
||||
{
|
||||
template <typename Graph,
|
||||
typename State_Name,
|
||||
typename Name_Hash = std::hash<State_Name>,
|
||||
typename Name_Equal = std::equal_to<State_Name>>
|
||||
typename State_Name,
|
||||
typename Name_Hash = std::hash<State_Name>,
|
||||
typename Name_Equal = std::equal_to<State_Name>>
|
||||
class SPOT_API named_graph
|
||||
{
|
||||
protected:
|
||||
|
|
@ -40,7 +40,7 @@ namespace spot
|
|||
typedef State_Name name;
|
||||
|
||||
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;
|
||||
typedef std::vector<name> state_to_name_t;
|
||||
state_to_name_t state_to_name;
|
||||
|
|
@ -65,14 +65,14 @@ namespace spot
|
|||
{
|
||||
auto p = name_to_state.emplace(n, 0U);
|
||||
if (p.second)
|
||||
{
|
||||
unsigned s = g_.new_state(std::forward<Args>(args)...);
|
||||
p.first->second = s;
|
||||
if (state_to_name.size() < s + 1)
|
||||
state_to_name.resize(s + 1);
|
||||
state_to_name[s] = n;
|
||||
return s;
|
||||
}
|
||||
{
|
||||
unsigned s = g_.new_state(std::forward<Args>(args)...);
|
||||
p.first->second = s;
|
||||
if (state_to_name.size() < s + 1)
|
||||
state_to_name.resize(s + 1);
|
||||
state_to_name[s] = n;
|
||||
return s;
|
||||
}
|
||||
return p.first->second;
|
||||
}
|
||||
|
||||
|
|
@ -85,27 +85,27 @@ namespace spot
|
|||
{
|
||||
auto p = name_to_state.emplace(newname, s);
|
||||
if (!p.second)
|
||||
{
|
||||
// The state already exists. Change its number.
|
||||
auto old = p.first->second;
|
||||
p.first->second = s;
|
||||
// Add the successor of OLD to those of S.
|
||||
auto& trans = g_.edge_vector();
|
||||
auto& states = g_.states();
|
||||
trans[states[s].succ_tail].next_succ = states[old].succ;
|
||||
states[s].succ_tail = states[old].succ_tail;
|
||||
states[old].succ = 0;
|
||||
states[old].succ_tail = 0;
|
||||
// Remove all references to old in edges:
|
||||
unsigned tend = trans.size();
|
||||
for (unsigned t = 1; t < tend; ++t)
|
||||
{
|
||||
if (trans[t].src == old)
|
||||
trans[t].src = s;
|
||||
if (trans[t].dst == old)
|
||||
trans[t].dst = s;
|
||||
}
|
||||
}
|
||||
{
|
||||
// The state already exists. Change its number.
|
||||
auto old = p.first->second;
|
||||
p.first->second = s;
|
||||
// Add the successor of OLD to those of S.
|
||||
auto& trans = g_.edge_vector();
|
||||
auto& states = g_.states();
|
||||
trans[states[s].succ_tail].next_succ = states[old].succ;
|
||||
states[s].succ_tail = states[old].succ_tail;
|
||||
states[old].succ = 0;
|
||||
states[old].succ_tail = 0;
|
||||
// Remove all references to old in edges:
|
||||
unsigned tend = trans.size();
|
||||
for (unsigned t = 1; t < tend; ++t)
|
||||
{
|
||||
if (trans[t].src == old)
|
||||
trans[t].src = s;
|
||||
if (trans[t].dst == old)
|
||||
trans[t].dst = s;
|
||||
}
|
||||
}
|
||||
return !p.second;
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ namespace spot
|
|||
new_edge(name src, name dst, Args&&... args)
|
||||
{
|
||||
return g_.new_edge(get_state(src), get_state(dst),
|
||||
std::forward<Args>(args)...);
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
|
|
@ -144,19 +144,19 @@ namespace spot
|
|||
std::vector<State_Name> d;
|
||||
d.reserve(dst.size());
|
||||
for (auto n: dst)
|
||||
d.push_back(get_state(n));
|
||||
d.push_back(get_state(n));
|
||||
return g_.new_edge(get_state(src), d, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
edge
|
||||
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;
|
||||
d.reserve(dst.size());
|
||||
for (auto n: dst)
|
||||
d.push_back(get_state(n));
|
||||
d.push_back(get_state(n));
|
||||
return g_.new_edge(get_state(src), d, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,16 +46,16 @@ namespace spot
|
|||
|
||||
// Do not simply return "other - this", it might not fit in an int.
|
||||
if (o < this)
|
||||
return -1;
|
||||
return -1;
|
||||
if (o > this)
|
||||
return 1;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual size_t hash() const override
|
||||
{
|
||||
return
|
||||
reinterpret_cast<const char*>(this) - static_cast<const char*>(nullptr);
|
||||
reinterpret_cast<const char*>(this) - static_cast<const char*>(nullptr);
|
||||
}
|
||||
|
||||
virtual kripke_graph_state*
|
||||
|
|
@ -93,7 +93,7 @@ namespace spot
|
|||
edge p_;
|
||||
public:
|
||||
kripke_graph_succ_iterator(const Graph* g,
|
||||
const typename Graph::state_storage_t* s):
|
||||
const typename Graph::state_storage_t* s):
|
||||
kripke_succ_iterator(s->cond()),
|
||||
g_(g),
|
||||
t_(s->succ)
|
||||
|
|
@ -131,7 +131,7 @@ namespace spot
|
|||
{
|
||||
assert(!done());
|
||||
return const_cast<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
|
||||
{
|
||||
if (num_states() == 0)
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
return init_number_;
|
||||
}
|
||||
|
||||
virtual const kripke_graph_state* get_init_state() const override
|
||||
{
|
||||
if (num_states() == 0)
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
return state_from_number(init_number_);
|
||||
}
|
||||
|
||||
|
|
@ -197,13 +197,13 @@ namespace spot
|
|||
assert(!s->succ || g_.valid_trans(s->succ));
|
||||
|
||||
if (this->iter_cache_)
|
||||
{
|
||||
auto it =
|
||||
down_cast<kripke_graph_succ_iterator<graph_t>*>(this->iter_cache_);
|
||||
it->recycle(s);
|
||||
this->iter_cache_ = nullptr;
|
||||
return it;
|
||||
}
|
||||
{
|
||||
auto it =
|
||||
down_cast<kripke_graph_succ_iterator<graph_t>*>(this->iter_cache_);
|
||||
it->recycle(s);
|
||||
this->iter_cache_ = nullptr;
|
||||
return it;
|
||||
}
|
||||
return new kripke_graph_succ_iterator<graph_t>(&g_, s);
|
||||
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -67,9 +67,9 @@ namespace spot
|
|||
// to enable compression, 2 to enable a faster compression that only
|
||||
// work if all variables are smaller than 2^28.
|
||||
kripke_ptr kripke(const atomic_prop_set* to_observe,
|
||||
bdd_dict_ptr dict,
|
||||
formula dead = formula::tt(),
|
||||
int compress = 0) const;
|
||||
bdd_dict_ptr dict,
|
||||
formula dead = formula::tt(),
|
||||
int compress = 0) const;
|
||||
|
||||
/// Number of variables in a state
|
||||
int state_size() const;
|
||||
|
|
|
|||
|
|
@ -32,12 +32,12 @@ namespace spot
|
|||
{
|
||||
// Bare words cannot be empty and should start with a letter.
|
||||
if (!*str
|
||||
|| !(isalpha(*str) || *str == '_' || *str == '.'))
|
||||
|| !(isalpha(*str) || *str == '_' || *str == '.'))
|
||||
return false;
|
||||
// The remaining of the word must be alphanumeric.
|
||||
while (*++str)
|
||||
if (!(isalnum(*str) || *str == '_' || *str == '.'))
|
||||
return false;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ namespace spot
|
|||
return false;
|
||||
while (*++str)
|
||||
if (!(isalnum(*str) || *str == '_'))
|
||||
return false;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace spot
|
|||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t n = (bitcount + bpb - 1) / bpb;
|
||||
if (n < 1)
|
||||
return 1;
|
||||
return 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
@ -60,12 +60,12 @@ namespace spot
|
|||
{
|
||||
static unsigned long init()
|
||||
{
|
||||
return 14695981039346656037UL;
|
||||
return 14695981039346656037UL;
|
||||
}
|
||||
|
||||
static unsigned long prime()
|
||||
{
|
||||
return 1099511628211UL;
|
||||
return 1099511628211UL;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
|
@ -76,12 +76,12 @@ namespace spot
|
|||
{
|
||||
static unsigned long init()
|
||||
{
|
||||
return 2166136261UL;
|
||||
return 2166136261UL;
|
||||
}
|
||||
|
||||
static unsigned long prime()
|
||||
{
|
||||
return 16777619UL;
|
||||
return 16777619UL;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ namespace spot
|
|||
// already contains one int of local_storage_, but
|
||||
// we allocate n-1 more so that we store the table.
|
||||
void* mem = operator new(sizeof(bitvect)
|
||||
+ (n - 1) * sizeof(bitvect::block_t));
|
||||
+ (n - 1) * sizeof(bitvect::block_t));
|
||||
bitvect* res = new(mem) bitvect(size_, n, true);
|
||||
memcpy(res->storage_, storage_, res->block_count_ * sizeof(block_t));
|
||||
return res;
|
||||
|
|
@ -125,8 +125,8 @@ namespace spot
|
|||
return res;
|
||||
for (i = 0; i < m - 1; ++i)
|
||||
{
|
||||
res ^= storage_[i];
|
||||
res *= fnv<sizeof(block_t)>::prime();
|
||||
res ^= storage_[i];
|
||||
res *= fnv<sizeof(block_t)>::prime();
|
||||
}
|
||||
// Deal with the last block, that might not be fully used.
|
||||
// Compute the number n of bits used in the last block.
|
||||
|
|
@ -144,7 +144,7 @@ namespace spot
|
|||
// already contains one int of local_storage_, but
|
||||
// we allocate n-1 more so that we store the table.
|
||||
void* mem = operator new(sizeof(bitvect)
|
||||
+ (n - 1) * sizeof(bitvect::block_t));
|
||||
+ (n - 1) * sizeof(bitvect::block_t));
|
||||
return new(mem) bitvect(bitcount, n);
|
||||
}
|
||||
|
||||
|
|
@ -176,16 +176,16 @@ namespace spot
|
|||
size_t end = a.size();
|
||||
if (end == 0)
|
||||
{
|
||||
os << "empty\n";
|
||||
return os;
|
||||
os << "empty\n";
|
||||
return os;
|
||||
}
|
||||
int w = floor(log10(end - 1)) + 1;
|
||||
for (size_t i = 0; i != end; ++i)
|
||||
{
|
||||
os.width(w);
|
||||
os << i;
|
||||
os.width(1);
|
||||
os << ": " << a.at(i) << '\n';
|
||||
os.width(w);
|
||||
os << i;
|
||||
os.width(1);
|
||||
os << ": " << a.at(i) << '\n';
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace spot
|
|||
///
|
||||
/// The resulting bitvect_array should be released with <code>delete</code>.
|
||||
SPOT_API bitvect_array* make_bitvect_array(size_t bitcount,
|
||||
size_t vectcount);
|
||||
size_t vectcount);
|
||||
|
||||
/// \brief A bit vector
|
||||
class SPOT_API bitvect
|
||||
|
|
@ -85,14 +85,14 @@ namespace spot
|
|||
reserve_blocks(other.block_count_);
|
||||
size_ = other.size();
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
storage_[i] = other.storage_[i];
|
||||
storage_[i] = other.storage_[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
~bitvect()
|
||||
{
|
||||
if (storage_ != &local_storage_)
|
||||
free(storage_);
|
||||
free(storage_);
|
||||
}
|
||||
|
||||
/// Grow the bitvector to \a new_block_count blocks.
|
||||
|
|
@ -101,20 +101,20 @@ namespace spot
|
|||
void reserve_blocks(size_t new_block_count)
|
||||
{
|
||||
if (new_block_count < block_count_)
|
||||
return;
|
||||
return;
|
||||
if (storage_ == &local_storage_)
|
||||
{
|
||||
block_t* new_storage_ = static_cast<block_t*>
|
||||
(malloc(new_block_count * sizeof(block_t)));
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
new_storage_[i] = storage_[i];
|
||||
storage_ = new_storage_;
|
||||
}
|
||||
{
|
||||
block_t* new_storage_ = static_cast<block_t*>
|
||||
(malloc(new_block_count * sizeof(block_t)));
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
new_storage_[i] = storage_[i];
|
||||
storage_ = new_storage_;
|
||||
}
|
||||
else
|
||||
{
|
||||
storage_ = static_cast<block_t*>
|
||||
(realloc(storage_, new_block_count * sizeof(block_t)));
|
||||
}
|
||||
{
|
||||
storage_ = static_cast<block_t*>
|
||||
(realloc(storage_, new_block_count * sizeof(block_t)));
|
||||
}
|
||||
block_count_ = new_block_count;
|
||||
}
|
||||
|
||||
|
|
@ -137,44 +137,44 @@ namespace spot
|
|||
void push_back(bool val)
|
||||
{
|
||||
if (size() == capacity())
|
||||
grow();
|
||||
grow();
|
||||
size_t pos = size_++;
|
||||
if (val)
|
||||
set(pos);
|
||||
set(pos);
|
||||
else
|
||||
clear(pos);
|
||||
clear(pos);
|
||||
}
|
||||
|
||||
/// \brief Append the lowest \a count bits of \a data.
|
||||
void push_back(block_t data, unsigned count)
|
||||
{
|
||||
if (size() + count > capacity())
|
||||
grow();
|
||||
grow();
|
||||
const size_t bpb = 8 * sizeof(block_t);
|
||||
|
||||
// Clear the higher bits.
|
||||
if (count != bpb)
|
||||
data &= (1UL << count) - 1;
|
||||
data &= (1UL << count) - 1;
|
||||
|
||||
size_t n = size() % bpb;
|
||||
size_t i = size_ / bpb;
|
||||
size_ += count;
|
||||
if (n == 0) // Aligned on block_t boundary
|
||||
{
|
||||
storage_[i] = data;
|
||||
}
|
||||
else // Only (bpb-n) bits free in this block.
|
||||
{
|
||||
// Take the lower bpb-n bits of data...
|
||||
block_t mask = (1UL << (bpb - n)) - 1;
|
||||
block_t data1 = (data & mask) << n;
|
||||
mask <<= n;
|
||||
// ... write them on the higher bpb-n bits of last block.
|
||||
storage_[i] = (storage_[i] & ~mask) | data1;
|
||||
// Write the remaining bits in the next block.
|
||||
if (bpb - n < count)
|
||||
storage_[i + 1] = data >> (bpb - n);
|
||||
}
|
||||
if (n == 0) // Aligned on block_t boundary
|
||||
{
|
||||
storage_[i] = data;
|
||||
}
|
||||
else // Only (bpb-n) bits free in this block.
|
||||
{
|
||||
// Take the lower bpb-n bits of data...
|
||||
block_t mask = (1UL << (bpb - n)) - 1;
|
||||
block_t data1 = (data & mask) << n;
|
||||
mask <<= n;
|
||||
// ... write them on the higher bpb-n bits of last block.
|
||||
storage_[i] = (storage_[i] & ~mask) | data1;
|
||||
// Write the remaining bits in the next block.
|
||||
if (bpb - n < count)
|
||||
storage_[i + 1] = data >> (bpb - n);
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
|
|
@ -199,7 +199,7 @@ namespace spot
|
|||
void clear_all()
|
||||
{
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
storage_[i] = 0;
|
||||
storage_[i] = 0;
|
||||
}
|
||||
|
||||
bool is_fully_clear() const
|
||||
|
|
@ -208,12 +208,12 @@ namespace spot
|
|||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t rest = size() % bpb;
|
||||
for (i = 0; i < block_count_ - !!rest; ++i)
|
||||
if (storage_[i] != 0)
|
||||
return false;
|
||||
if (storage_[i] != 0)
|
||||
return false;
|
||||
// The last block might not be fully used, compare only the
|
||||
// relevant portion.
|
||||
if (!rest)
|
||||
return true;
|
||||
return true;
|
||||
block_t mask = (1UL << rest) - 1;
|
||||
return (storage_[i] & mask) == 0;
|
||||
}
|
||||
|
|
@ -224,10 +224,10 @@ namespace spot
|
|||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t rest = size() % bpb;
|
||||
for (i = 0; i < block_count_ - !!rest; ++i)
|
||||
if (storage_[i] != -1UL)
|
||||
return false;
|
||||
if (storage_[i] != -1UL)
|
||||
return false;
|
||||
if (!rest)
|
||||
return true;
|
||||
return true;
|
||||
// The last block might not be fully used, compare only the
|
||||
// relevant portion.
|
||||
block_t mask = (1UL << rest) - 1;
|
||||
|
|
@ -237,13 +237,13 @@ namespace spot
|
|||
void set_all()
|
||||
{
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
storage_[i] = -1UL;
|
||||
storage_[i] = -1UL;
|
||||
}
|
||||
|
||||
void flip_all()
|
||||
{
|
||||
for (size_t i = 0; i < block_count_; ++i)
|
||||
storage_[i] = ~storage_[i];
|
||||
storage_[i] = ~storage_[i];
|
||||
}
|
||||
|
||||
void set(size_t pos)
|
||||
|
|
@ -273,7 +273,7 @@ namespace spot
|
|||
assert(other.size_ <= size_);
|
||||
unsigned m = std::min(other.block_count_, block_count_);
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
storage_[i] |= other.storage_[i];
|
||||
storage_[i] |= other.storage_[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -282,7 +282,7 @@ namespace spot
|
|||
assert(other.size_ <= size_);
|
||||
unsigned m = std::min(other.block_count_, block_count_);
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
storage_[i] &= other.storage_[i];
|
||||
storage_[i] &= other.storage_[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ namespace spot
|
|||
assert(other.size_ <= size_);
|
||||
unsigned m = std::min(other.block_count_, block_count_);
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
storage_[i] ^= other.storage_[i];
|
||||
storage_[i] ^= other.storage_[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -299,7 +299,7 @@ namespace spot
|
|||
{
|
||||
assert(other.block_count_ <= block_count_);
|
||||
for (size_t i = 0; i < other.block_count_; ++i)
|
||||
storage_[i] &= ~other.storage_[i];
|
||||
storage_[i] &= ~other.storage_[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -311,33 +311,33 @@ namespace spot
|
|||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t rest = size() % bpb;
|
||||
for (i = 0; i < block_count_ - !!rest; ++i)
|
||||
if ((storage_[i] & other.storage_[i]) != other.storage_[i])
|
||||
return false;
|
||||
if ((storage_[i] & other.storage_[i]) != other.storage_[i])
|
||||
return false;
|
||||
if (!rest)
|
||||
return true;
|
||||
return true;
|
||||
|
||||
// The last block might not be fully used, compare only the
|
||||
// relevant portion.
|
||||
block_t mask = (1UL << rest) - 1;
|
||||
return ((storage_[i] & mask & other.storage_[i])
|
||||
== (other.storage_[i] & mask));
|
||||
== (other.storage_[i] & mask));
|
||||
}
|
||||
|
||||
bool operator==(const bitvect& other) const
|
||||
{
|
||||
if (other.size_ != size_)
|
||||
return false;
|
||||
return false;
|
||||
if (size_ == 0)
|
||||
return true;
|
||||
return true;
|
||||
size_t i;
|
||||
size_t m = other.used_blocks();
|
||||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t rest = size() % bpb;
|
||||
for (i = 0; i < m - !!rest; ++i)
|
||||
if (storage_[i] != other.storage_[i])
|
||||
return false;
|
||||
if (storage_[i] != other.storage_[i])
|
||||
return false;
|
||||
if (!rest)
|
||||
return true;
|
||||
return true;
|
||||
// The last block might not be fully used, compare only the
|
||||
// relevant portion.
|
||||
block_t mask = (1UL << rest) - 1;
|
||||
|
|
@ -352,18 +352,18 @@ namespace spot
|
|||
bool operator<(const bitvect& other) const
|
||||
{
|
||||
if (size_ != other.size_)
|
||||
return size_ < other.size_;
|
||||
return size_ < other.size_;
|
||||
if (size_ == 0)
|
||||
return false;
|
||||
return false;
|
||||
size_t i;
|
||||
size_t m = other.used_blocks();
|
||||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
size_t rest = size() % bpb;
|
||||
for (i = 0; i < m - !!rest; ++i)
|
||||
if (storage_[i] > other.storage_[i])
|
||||
return false;
|
||||
if (storage_[i] > other.storage_[i])
|
||||
return false;
|
||||
if (!rest)
|
||||
return true;
|
||||
return true;
|
||||
// The last block might not be fully used, compare only the
|
||||
// relevant portion.
|
||||
block_t mask = (1UL << rest) - 1;
|
||||
|
|
@ -398,7 +398,7 @@ namespace spot
|
|||
res->make_empty();
|
||||
|
||||
if (end == begin)
|
||||
return res;
|
||||
return res;
|
||||
|
||||
const size_t bpb = 8 * sizeof(bitvect::block_t);
|
||||
|
||||
|
|
@ -407,32 +407,32 @@ namespace spot
|
|||
size_t indexe = (end - 1) / bpb;
|
||||
|
||||
if (indexb == indexe)
|
||||
{
|
||||
block_t data = storage_[indexb];
|
||||
data >>= bitb;
|
||||
res->push_back(data, count);
|
||||
}
|
||||
{
|
||||
block_t data = storage_[indexb];
|
||||
data >>= bitb;
|
||||
res->push_back(data, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
block_t data = storage_[indexb];
|
||||
data >>= bitb;
|
||||
res->push_back(data, bpb - bitb);
|
||||
count -= bpb - bitb;
|
||||
while (count >= bpb)
|
||||
{
|
||||
++indexb;
|
||||
res->push_back(storage_[indexb], bpb);
|
||||
count -= bpb;
|
||||
assert(indexb != indexe || count == 0);
|
||||
}
|
||||
if (count > 0)
|
||||
{
|
||||
++indexb;
|
||||
assert(indexb == indexe);
|
||||
assert(count == end % bpb);
|
||||
res->push_back(storage_[indexb], count);
|
||||
}
|
||||
}
|
||||
{
|
||||
block_t data = storage_[indexb];
|
||||
data >>= bitb;
|
||||
res->push_back(data, bpb - bitb);
|
||||
count -= bpb - bitb;
|
||||
while (count >= bpb)
|
||||
{
|
||||
++indexb;
|
||||
res->push_back(storage_[indexb], bpb);
|
||||
count -= bpb;
|
||||
assert(indexb != indexe || count == 0);
|
||||
}
|
||||
if (count > 0)
|
||||
{
|
||||
++indexb;
|
||||
assert(indexb == indexe);
|
||||
assert(count == end % bpb);
|
||||
res->push_back(storage_[indexb], count);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -441,12 +441,12 @@ namespace spot
|
|||
|
||||
/// Print a bitvect.
|
||||
friend SPOT_API std::ostream& operator<<(std::ostream&,
|
||||
const bitvect&);
|
||||
const bitvect&);
|
||||
|
||||
private:
|
||||
friend SPOT_API bitvect_array*
|
||||
::spot::make_bitvect_array(size_t bitcount,
|
||||
size_t vectcount);
|
||||
size_t vectcount);
|
||||
|
||||
size_t size_;
|
||||
size_t block_count_;
|
||||
|
|
@ -485,7 +485,7 @@ namespace spot
|
|||
~bitvect_array()
|
||||
{
|
||||
for (size_t i = 0; i < size_; ++i)
|
||||
at(i).~bitvect();
|
||||
at(i).~bitvect();
|
||||
}
|
||||
|
||||
/// The number of bitvect in the array.
|
||||
|
|
@ -506,7 +506,7 @@ namespace spot
|
|||
// FIXME: This could be changed into a large memset if the
|
||||
// individual vectors where not allowed to be reallocated.
|
||||
for (unsigned s = 0; s < size_; s++)
|
||||
at(s).clear_all();
|
||||
at(s).clear_all();
|
||||
}
|
||||
|
||||
/// Return the bit-vector at \a index.
|
||||
|
|
@ -518,12 +518,12 @@ namespace spot
|
|||
|
||||
friend SPOT_API bitvect_array*
|
||||
::spot::make_bitvect_array(size_t bitcount,
|
||||
size_t vectcount);
|
||||
size_t vectcount);
|
||||
|
||||
|
||||
/// Print a bitvect_array.
|
||||
friend SPOT_API std::ostream& operator<<(std::ostream&,
|
||||
const bitvect_array&);
|
||||
const bitvect_array&);
|
||||
|
||||
private:
|
||||
size_t size_;
|
||||
|
|
|
|||
|
|
@ -93,9 +93,9 @@
|
|||
|
||||
// The extra parentheses in assert() is so that this
|
||||
// pattern is not caught by the style checker.
|
||||
#define SPOT_UNREACHABLE() do { \
|
||||
assert(!("unreachable code reached")); \
|
||||
SPOT_UNREACHABLE_BUILTIN(); \
|
||||
#define SPOT_UNREACHABLE() do { \
|
||||
assert(!("unreachable code reached")); \
|
||||
SPOT_UNREACHABLE_BUILTIN(); \
|
||||
} while (0)
|
||||
|
||||
#define SPOT_UNIMPLEMENTED() throw std::runtime_error("unimplemented");
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ namespace spot
|
|||
{
|
||||
for (auto i: str)
|
||||
switch (i)
|
||||
{
|
||||
case '"':
|
||||
os << "\"\"";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
{
|
||||
case '"':
|
||||
os << "\"\"";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
|
@ -49,28 +49,28 @@ namespace spot
|
|||
{
|
||||
for (auto i: str)
|
||||
switch (i)
|
||||
{
|
||||
case '~':
|
||||
os << "\\text{\\textasciitilde}";
|
||||
break;
|
||||
case '^':
|
||||
os << "\\text{\\textasciicircum}";
|
||||
break;
|
||||
case '\\':
|
||||
os << "\\text{\\textbackslash}";
|
||||
break;
|
||||
case '&':
|
||||
case '%':
|
||||
case '$':
|
||||
case '#':
|
||||
case '_':
|
||||
case '{':
|
||||
case '}':
|
||||
os << '\\';
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
{
|
||||
case '~':
|
||||
os << "\\text{\\textasciitilde}";
|
||||
break;
|
||||
case '^':
|
||||
os << "\\text{\\textasciicircum}";
|
||||
break;
|
||||
case '\\':
|
||||
os << "\\text{\\textbackslash}";
|
||||
break;
|
||||
case '&':
|
||||
case '%':
|
||||
case '$':
|
||||
case '#':
|
||||
case '_':
|
||||
case '{':
|
||||
case '}':
|
||||
os << '\\';
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
|
@ -79,23 +79,23 @@ namespace spot
|
|||
{
|
||||
for (auto i: str)
|
||||
switch (i)
|
||||
{
|
||||
case '&':
|
||||
os << "&";
|
||||
break;
|
||||
case '"':
|
||||
os << """;
|
||||
break;
|
||||
case '<':
|
||||
os << "<";
|
||||
break;
|
||||
case '>':
|
||||
os << ">";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
{
|
||||
case '&':
|
||||
os << "&";
|
||||
break;
|
||||
case '"':
|
||||
os << """;
|
||||
break;
|
||||
case '<':
|
||||
os << "<";
|
||||
break;
|
||||
case '>':
|
||||
os << ">";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
|
@ -104,20 +104,20 @@ namespace spot
|
|||
{
|
||||
for (auto i: str)
|
||||
switch (i)
|
||||
{
|
||||
case '\\':
|
||||
os << "\\\\";
|
||||
break;
|
||||
case '"':
|
||||
os << "\\\"";
|
||||
break;
|
||||
case '\n':
|
||||
os << "\\n";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
{
|
||||
case '\\':
|
||||
os << "\\\\";
|
||||
break;
|
||||
case '"':
|
||||
os << "\\\"";
|
||||
break;
|
||||
case '\n':
|
||||
os << "\\n";
|
||||
break;
|
||||
default:
|
||||
os << i;
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
|
@ -135,26 +135,26 @@ namespace spot
|
|||
// Single quotes are best, unless the string to quote contains one.
|
||||
if (!strchr(str, '\''))
|
||||
{
|
||||
os << '\'' << str << '\'';
|
||||
os << '\'' << str << '\'';
|
||||
}
|
||||
else
|
||||
{
|
||||
// In double quotes we have to escape $ ` " or \.
|
||||
os << '"';
|
||||
while (*str)
|
||||
switch (*str)
|
||||
{
|
||||
case '$':
|
||||
case '`':
|
||||
case '"':
|
||||
case '\\':
|
||||
os << '\\';
|
||||
// fall through
|
||||
default:
|
||||
os << *str++;
|
||||
break;
|
||||
}
|
||||
os << '"';
|
||||
// In double quotes we have to escape $ ` " or \.
|
||||
os << '"';
|
||||
while (*str)
|
||||
switch (*str)
|
||||
{
|
||||
case '$':
|
||||
case '`':
|
||||
case '"':
|
||||
case '\\':
|
||||
os << '\\';
|
||||
// fall through
|
||||
default:
|
||||
os << *str++;
|
||||
break;
|
||||
}
|
||||
os << '"';
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,22 +34,22 @@ namespace spot
|
|||
/// Create a pool allocating objects of \a size bytes.
|
||||
fixed_size_pool(size_t size)
|
||||
: freelist_(nullptr), free_start_(nullptr),
|
||||
free_end_(nullptr), chunklist_(nullptr)
|
||||
free_end_(nullptr), chunklist_(nullptr)
|
||||
{
|
||||
const size_t alignement = 2 * sizeof(size_t);
|
||||
size_ = ((size >= sizeof(block_) ? size : sizeof(block_))
|
||||
+ alignement - 1) & ~(alignement - 1);
|
||||
+ alignement - 1) & ~(alignement - 1);
|
||||
}
|
||||
|
||||
/// Free any memory allocated by this pool.
|
||||
~fixed_size_pool()
|
||||
{
|
||||
while (chunklist_)
|
||||
{
|
||||
chunk_* prev = chunklist_->prev;
|
||||
free(chunklist_);
|
||||
chunklist_ = prev;
|
||||
}
|
||||
{
|
||||
chunk_* prev = chunklist_->prev;
|
||||
free(chunklist_);
|
||||
chunklist_ = prev;
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocate \a size bytes of memory.
|
||||
|
|
@ -59,27 +59,27 @@ namespace spot
|
|||
block_* f = freelist_;
|
||||
// If we have free blocks available, return the first one.
|
||||
if (f)
|
||||
{
|
||||
freelist_ = f->next;
|
||||
return f;
|
||||
}
|
||||
{
|
||||
freelist_ = f->next;
|
||||
return f;
|
||||
}
|
||||
|
||||
// Else, create a block out of the last chunk of allocated
|
||||
// memory.
|
||||
|
||||
// If all the last chunk has been used, allocate one more.
|
||||
if (free_start_ + size_ > free_end_)
|
||||
{
|
||||
const size_t requested = (size_ > 128 ? size_ : 128) * 8192 - 64;
|
||||
chunk_* c = reinterpret_cast<chunk_*>(malloc(requested));
|
||||
if (!c)
|
||||
throw std::bad_alloc();
|
||||
c->prev = chunklist_;
|
||||
chunklist_ = c;
|
||||
{
|
||||
const size_t requested = (size_ > 128 ? size_ : 128) * 8192 - 64;
|
||||
chunk_* c = reinterpret_cast<chunk_*>(malloc(requested));
|
||||
if (!c)
|
||||
throw std::bad_alloc();
|
||||
c->prev = chunklist_;
|
||||
chunklist_ = c;
|
||||
|
||||
free_start_ = c->data_ + size_;
|
||||
free_end_ = c->data_ + requested;
|
||||
}
|
||||
free_start_ = c->data_ + size_;
|
||||
free_end_ = c->data_ + requested;
|
||||
}
|
||||
|
||||
void* res = free_start_;
|
||||
free_start_ += size_;
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@ namespace spot
|
|||
{
|
||||
for (const char* pos = fmt; *pos; ++pos)
|
||||
if (*pos == '%')
|
||||
{
|
||||
char c = *++pos;
|
||||
has[c] = true;
|
||||
if (!c)
|
||||
break;
|
||||
}
|
||||
{
|
||||
char c = *++pos;
|
||||
has[c] = true;
|
||||
if (!c)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -46,17 +46,17 @@ namespace spot
|
|||
formater::format(const char* fmt)
|
||||
{
|
||||
for (const char* pos = fmt; *pos; ++pos)
|
||||
if (*pos != '%')
|
||||
{
|
||||
*output_ << *pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
char c = *++pos;
|
||||
call_[c]->print(*output_, pos);
|
||||
if (!c)
|
||||
break;
|
||||
}
|
||||
if (*pos != '%')
|
||||
{
|
||||
*output_ << *pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
char c = *++pos;
|
||||
call_[c]->print(*output_, pos);
|
||||
if (!c)
|
||||
break;
|
||||
}
|
||||
return *output_;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ namespace spot
|
|||
size_t operator()(const T* p) const
|
||||
{
|
||||
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;
|
||||
|
||||
return wang32_hash(static_cast<size_t>(th(p.first)) ^
|
||||
static_cast<size_t>(uh(p.second)));
|
||||
static_cast<size_t>(uh(p.second)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,270 +43,270 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
stream_compression_base(size_t size)
|
||||
: size_(size)
|
||||
: size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
static const unsigned bits_width[7] = { 1, 3, 5, 7, 9, 14, 28 };
|
||||
static const unsigned max_count[8] = { 30, 10, 6, 4, 3, 2, 1, 0 };
|
||||
static const unsigned max_allowed[8] = { 1,
|
||||
(1 << 3) - 1,
|
||||
(1 << 5) - 1,
|
||||
(1 << 7) - 1,
|
||||
(1 << 9) - 1,
|
||||
(1 << 14) - 1,
|
||||
(1 << 28) - 1,
|
||||
-1U };
|
||||
// If we have only X data to compress and they fit with the
|
||||
// current bit width, the following table tells us we should
|
||||
// use bits_width[count_to_level[X - 1]] to limit the number
|
||||
// of trailing zeros we encode. E.g. count_to_level[5 - 1]
|
||||
// is 2, which mean that 5 values should be encoded with
|
||||
// bits_width[2] == 5 bits.
|
||||
static const unsigned count_to_level[30] =
|
||||
{
|
||||
6, // 1
|
||||
5, // 2
|
||||
4, // 3
|
||||
3, // 4
|
||||
2, // 5
|
||||
2, // 6
|
||||
1, // 7
|
||||
1, // 8
|
||||
1, // 9
|
||||
1, // 10
|
||||
0, 0, 0, 0, 0, // 11-15
|
||||
0, 0, 0, 0, 0, // 16-20
|
||||
0, 0, 0, 0, 0, // 21-25
|
||||
0, 0, 0, 0, 0, // 26-30
|
||||
};
|
||||
static const unsigned bits_width[7] = { 1, 3, 5, 7, 9, 14, 28 };
|
||||
static const unsigned max_count[8] = { 30, 10, 6, 4, 3, 2, 1, 0 };
|
||||
static const unsigned max_allowed[8] = { 1,
|
||||
(1 << 3) - 1,
|
||||
(1 << 5) - 1,
|
||||
(1 << 7) - 1,
|
||||
(1 << 9) - 1,
|
||||
(1 << 14) - 1,
|
||||
(1 << 28) - 1,
|
||||
-1U };
|
||||
// If we have only X data to compress and they fit with the
|
||||
// current bit width, the following table tells us we should
|
||||
// use bits_width[count_to_level[X - 1]] to limit the number
|
||||
// of trailing zeros we encode. E.g. count_to_level[5 - 1]
|
||||
// is 2, which mean that 5 values should be encoded with
|
||||
// bits_width[2] == 5 bits.
|
||||
static const unsigned count_to_level[30] =
|
||||
{
|
||||
6, // 1
|
||||
5, // 2
|
||||
4, // 3
|
||||
3, // 4
|
||||
2, // 5
|
||||
2, // 6
|
||||
1, // 7
|
||||
1, // 8
|
||||
1, // 9
|
||||
1, // 10
|
||||
0, 0, 0, 0, 0, // 11-15
|
||||
0, 0, 0, 0, 0, // 16-20
|
||||
0, 0, 0, 0, 0, // 21-25
|
||||
0, 0, 0, 0, 0, // 26-30
|
||||
};
|
||||
|
||||
while (size_ > 0)
|
||||
{
|
||||
unsigned id = 0; // Current level in the above two tables.
|
||||
unsigned curmax_allowed = max_allowed[id];
|
||||
unsigned compressable = 0; // Number of integers ready to pack.
|
||||
do
|
||||
{
|
||||
unsigned int val = self().data_at(compressable);
|
||||
++compressable;
|
||||
while (val > curmax_allowed)
|
||||
{
|
||||
curmax_allowed = max_allowed[++id];
|
||||
while (size_ > 0)
|
||||
{
|
||||
unsigned id = 0; // Current level in the above two tables.
|
||||
unsigned curmax_allowed = max_allowed[id];
|
||||
unsigned compressable = 0; // Number of integers ready to pack.
|
||||
do
|
||||
{
|
||||
unsigned int val = self().data_at(compressable);
|
||||
++compressable;
|
||||
while (val > curmax_allowed)
|
||||
{
|
||||
curmax_allowed = max_allowed[++id];
|
||||
|
||||
if (compressable > max_count[id])
|
||||
goto fast_encode;
|
||||
}
|
||||
if (compressable >= max_count[id])
|
||||
goto fast_encode;
|
||||
}
|
||||
while (SPOT_LIKELY(compressable < size_));
|
||||
if (compressable > max_count[id])
|
||||
goto fast_encode;
|
||||
}
|
||||
if (compressable >= max_count[id])
|
||||
goto fast_encode;
|
||||
}
|
||||
while (SPOT_LIKELY(compressable < size_));
|
||||
|
||||
assert(compressable < max_count[id]);
|
||||
assert(compressable < max_count[id]);
|
||||
|
||||
// Since we have less data than the current "id" allows,
|
||||
// try to use more bits so we can encode faster.
|
||||
// Since we have less data than the current "id" allows,
|
||||
// try to use more bits so we can encode faster.
|
||||
|
||||
id = count_to_level[compressable - 1];
|
||||
id = count_to_level[compressable - 1];
|
||||
|
||||
if (compressable == max_count[id])
|
||||
goto fast_encode;
|
||||
if (compressable == max_count[id])
|
||||
goto fast_encode;
|
||||
|
||||
// Slow compression for situations where we have
|
||||
// compressable < max_count[id]. We can only be in
|
||||
// one of the 3 first "id" (1, 3, or 5 bits);
|
||||
{
|
||||
assert(id <= 2);
|
||||
unsigned bits = bits_width[id];
|
||||
unsigned finalshifts = (max_count[id] - compressable) * bits;
|
||||
size_t pos = 0;
|
||||
unsigned output = self().data_at(pos);
|
||||
while (--compressable)
|
||||
{
|
||||
output <<= bits;
|
||||
output += self().data_at(++pos);
|
||||
}
|
||||
output <<= finalshifts;
|
||||
output += id << 30;
|
||||
self().push_data(output);
|
||||
return;
|
||||
}
|
||||
// Slow compression for situations where we have
|
||||
// compressable < max_count[id]. We can only be in
|
||||
// one of the 3 first "id" (1, 3, or 5 bits);
|
||||
{
|
||||
assert(id <= 2);
|
||||
unsigned bits = bits_width[id];
|
||||
unsigned finalshifts = (max_count[id] - compressable) * bits;
|
||||
size_t pos = 0;
|
||||
unsigned output = self().data_at(pos);
|
||||
while (--compressable)
|
||||
{
|
||||
output <<= bits;
|
||||
output += self().data_at(++pos);
|
||||
}
|
||||
output <<= finalshifts;
|
||||
output += id << 30;
|
||||
self().push_data(output);
|
||||
return;
|
||||
}
|
||||
|
||||
fast_encode:
|
||||
switch (id)
|
||||
{
|
||||
case 0: // 30 1-bit values
|
||||
{
|
||||
// This code has been tuned so that the compiler can
|
||||
// efficiently encode it as a series of MOV+LEA
|
||||
// instructions, without shifts. For instance
|
||||
//
|
||||
// output <<= 1;
|
||||
// output += self().data_at(4);
|
||||
//
|
||||
// translates to (assuming %eax points to the input,
|
||||
// and %edx holds the output) the following:
|
||||
//
|
||||
// mov ecx, [eax+16]
|
||||
// lea edx, [ecx+edx*2]
|
||||
//
|
||||
// This optimization is the reason why we use 'output +='
|
||||
// instead of the more intuitive 'output |=' everywhere in
|
||||
// this file.
|
||||
fast_encode:
|
||||
switch (id)
|
||||
{
|
||||
case 0: // 30 1-bit values
|
||||
{
|
||||
// This code has been tuned so that the compiler can
|
||||
// efficiently encode it as a series of MOV+LEA
|
||||
// instructions, without shifts. For instance
|
||||
//
|
||||
// output <<= 1;
|
||||
// output += self().data_at(4);
|
||||
//
|
||||
// translates to (assuming %eax points to the input,
|
||||
// and %edx holds the output) the following:
|
||||
//
|
||||
// mov ecx, [eax+16]
|
||||
// lea edx, [ecx+edx*2]
|
||||
//
|
||||
// This optimization is the reason why we use 'output +='
|
||||
// instead of the more intuitive 'output |=' everywhere in
|
||||
// this file.
|
||||
|
||||
unsigned int output = 0x00 << 1; // 00
|
||||
output += self().data_at(0);
|
||||
output <<= 1;
|
||||
output += self().data_at(1);
|
||||
output <<= 1;
|
||||
output += self().data_at(2);
|
||||
output <<= 1;
|
||||
output += self().data_at(3);
|
||||
output <<= 1;
|
||||
output += self().data_at(4);
|
||||
output <<= 1;
|
||||
output += self().data_at(5);
|
||||
output <<= 1;
|
||||
output += self().data_at(6);
|
||||
output <<= 1;
|
||||
output += self().data_at(7);
|
||||
output <<= 1;
|
||||
output += self().data_at(8);
|
||||
output <<= 1;
|
||||
output += self().data_at(9);
|
||||
output <<= 1;
|
||||
output += self().data_at(10);
|
||||
output <<= 1;
|
||||
output += self().data_at(11);
|
||||
output <<= 1;
|
||||
output += self().data_at(12);
|
||||
output <<= 1;
|
||||
output += self().data_at(13);
|
||||
output <<= 1;
|
||||
output += self().data_at(14);
|
||||
output <<= 1;
|
||||
output += self().data_at(15);
|
||||
output <<= 1;
|
||||
output += self().data_at(16);
|
||||
output <<= 1;
|
||||
output += self().data_at(17);
|
||||
output <<= 1;
|
||||
output += self().data_at(18);
|
||||
output <<= 1;
|
||||
output += self().data_at(19);
|
||||
output <<= 1;
|
||||
output += self().data_at(20);
|
||||
output <<= 1;
|
||||
output += self().data_at(21);
|
||||
output <<= 1;
|
||||
output += self().data_at(22);
|
||||
output <<= 1;
|
||||
output += self().data_at(23);
|
||||
output <<= 1;
|
||||
output += self().data_at(24);
|
||||
output <<= 1;
|
||||
output += self().data_at(25);
|
||||
output <<= 1;
|
||||
output += self().data_at(26);
|
||||
output <<= 1;
|
||||
output += self().data_at(27);
|
||||
output <<= 1;
|
||||
output += self().data_at(28);
|
||||
output <<= 1;
|
||||
output += self().data_at(29);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 1: // 10 3-bit values
|
||||
{
|
||||
// This code has been tuned so that the compiler can
|
||||
// efficiently encode it as a series of MOV+LEA
|
||||
// instructions, without shifts. For instance
|
||||
//
|
||||
// output <<= 3;
|
||||
// output += self().data_at(4);
|
||||
//
|
||||
// translates to (assuming %eax points to the input,
|
||||
// and %edx holds the output) the following:
|
||||
//
|
||||
// mov ecx, [eax+16]
|
||||
// lea edx, [ecx+edx*8]
|
||||
unsigned int output = 0x00 << 1; // 00
|
||||
output += self().data_at(0);
|
||||
output <<= 1;
|
||||
output += self().data_at(1);
|
||||
output <<= 1;
|
||||
output += self().data_at(2);
|
||||
output <<= 1;
|
||||
output += self().data_at(3);
|
||||
output <<= 1;
|
||||
output += self().data_at(4);
|
||||
output <<= 1;
|
||||
output += self().data_at(5);
|
||||
output <<= 1;
|
||||
output += self().data_at(6);
|
||||
output <<= 1;
|
||||
output += self().data_at(7);
|
||||
output <<= 1;
|
||||
output += self().data_at(8);
|
||||
output <<= 1;
|
||||
output += self().data_at(9);
|
||||
output <<= 1;
|
||||
output += self().data_at(10);
|
||||
output <<= 1;
|
||||
output += self().data_at(11);
|
||||
output <<= 1;
|
||||
output += self().data_at(12);
|
||||
output <<= 1;
|
||||
output += self().data_at(13);
|
||||
output <<= 1;
|
||||
output += self().data_at(14);
|
||||
output <<= 1;
|
||||
output += self().data_at(15);
|
||||
output <<= 1;
|
||||
output += self().data_at(16);
|
||||
output <<= 1;
|
||||
output += self().data_at(17);
|
||||
output <<= 1;
|
||||
output += self().data_at(18);
|
||||
output <<= 1;
|
||||
output += self().data_at(19);
|
||||
output <<= 1;
|
||||
output += self().data_at(20);
|
||||
output <<= 1;
|
||||
output += self().data_at(21);
|
||||
output <<= 1;
|
||||
output += self().data_at(22);
|
||||
output <<= 1;
|
||||
output += self().data_at(23);
|
||||
output <<= 1;
|
||||
output += self().data_at(24);
|
||||
output <<= 1;
|
||||
output += self().data_at(25);
|
||||
output <<= 1;
|
||||
output += self().data_at(26);
|
||||
output <<= 1;
|
||||
output += self().data_at(27);
|
||||
output <<= 1;
|
||||
output += self().data_at(28);
|
||||
output <<= 1;
|
||||
output += self().data_at(29);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 1: // 10 3-bit values
|
||||
{
|
||||
// This code has been tuned so that the compiler can
|
||||
// efficiently encode it as a series of MOV+LEA
|
||||
// instructions, without shifts. For instance
|
||||
//
|
||||
// output <<= 3;
|
||||
// output += self().data_at(4);
|
||||
//
|
||||
// translates to (assuming %eax points to the input,
|
||||
// and %edx holds the output) the following:
|
||||
//
|
||||
// mov ecx, [eax+16]
|
||||
// lea edx, [ecx+edx*8]
|
||||
|
||||
unsigned int output = 0x01 << 3; // 01
|
||||
output += self().data_at(0);
|
||||
output <<= 3;
|
||||
output += self().data_at(1);
|
||||
output <<= 3;
|
||||
output += self().data_at(2);
|
||||
output <<= 3;
|
||||
output += self().data_at(3);
|
||||
output <<= 3;
|
||||
output += self().data_at(4);
|
||||
output <<= 3;
|
||||
output += self().data_at(5);
|
||||
output <<= 3;
|
||||
output += self().data_at(6);
|
||||
output <<= 3;
|
||||
output += self().data_at(7);
|
||||
output <<= 3;
|
||||
output += self().data_at(8);
|
||||
output <<= 3;
|
||||
output += self().data_at(9);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 2: // 6 5-bit values
|
||||
{
|
||||
unsigned int output = 0x02U << 30; // 10
|
||||
output += self().data_at(0) << 25;
|
||||
output += self().data_at(1) << 20;
|
||||
output += self().data_at(2) << 15;
|
||||
output += self().data_at(3) << 10;
|
||||
output += self().data_at(4) << 5;
|
||||
output += self().data_at(5);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 3: // 4 7-bit values
|
||||
{
|
||||
unsigned int output = 0x0CU << 28; // 1100
|
||||
output += self().data_at(0) << 21;
|
||||
output += self().data_at(1) << 14;
|
||||
output += self().data_at(2) << 7;
|
||||
output += self().data_at(3);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 4: // 3 9-bit values
|
||||
{
|
||||
unsigned int output = 0x0DU << 28; // 1101x (1 bit lost)
|
||||
output += self().data_at(0) << 18;
|
||||
output += self().data_at(1) << 9;
|
||||
output += self().data_at(2);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 5: // 2 14-bit values
|
||||
{
|
||||
unsigned int output = 0x0EU << 28; // 1110
|
||||
output += self().data_at(0) << 14;
|
||||
output += self().data_at(1);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 6: // one 28-bit value
|
||||
{
|
||||
unsigned int output = 0x0FU << 28; // 1111
|
||||
output += self().data_at(0);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
}
|
||||
self().forward(max_count[id]);
|
||||
size_ -= max_count[id];
|
||||
}
|
||||
unsigned int output = 0x01 << 3; // 01
|
||||
output += self().data_at(0);
|
||||
output <<= 3;
|
||||
output += self().data_at(1);
|
||||
output <<= 3;
|
||||
output += self().data_at(2);
|
||||
output <<= 3;
|
||||
output += self().data_at(3);
|
||||
output <<= 3;
|
||||
output += self().data_at(4);
|
||||
output <<= 3;
|
||||
output += self().data_at(5);
|
||||
output <<= 3;
|
||||
output += self().data_at(6);
|
||||
output <<= 3;
|
||||
output += self().data_at(7);
|
||||
output <<= 3;
|
||||
output += self().data_at(8);
|
||||
output <<= 3;
|
||||
output += self().data_at(9);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 2: // 6 5-bit values
|
||||
{
|
||||
unsigned int output = 0x02U << 30; // 10
|
||||
output += self().data_at(0) << 25;
|
||||
output += self().data_at(1) << 20;
|
||||
output += self().data_at(2) << 15;
|
||||
output += self().data_at(3) << 10;
|
||||
output += self().data_at(4) << 5;
|
||||
output += self().data_at(5);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 3: // 4 7-bit values
|
||||
{
|
||||
unsigned int output = 0x0CU << 28; // 1100
|
||||
output += self().data_at(0) << 21;
|
||||
output += self().data_at(1) << 14;
|
||||
output += self().data_at(2) << 7;
|
||||
output += self().data_at(3);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 4: // 3 9-bit values
|
||||
{
|
||||
unsigned int output = 0x0DU << 28; // 1101x (1 bit lost)
|
||||
output += self().data_at(0) << 18;
|
||||
output += self().data_at(1) << 9;
|
||||
output += self().data_at(2);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 5: // 2 14-bit values
|
||||
{
|
||||
unsigned int output = 0x0EU << 28; // 1110
|
||||
output += self().data_at(0) << 14;
|
||||
output += self().data_at(1);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
case 6: // one 28-bit value
|
||||
{
|
||||
unsigned int output = 0x0FU << 28; // 1111
|
||||
output += self().data_at(0);
|
||||
self().push_data(output);
|
||||
}
|
||||
break;
|
||||
}
|
||||
self().forward(max_count[id]);
|
||||
size_ -= max_count[id];
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -315,12 +315,12 @@ namespace spot
|
|||
|
||||
Self& self()
|
||||
{
|
||||
return static_cast<Self&>(*this);
|
||||
return static_cast<Self&>(*this);
|
||||
}
|
||||
|
||||
const Self& self() const
|
||||
{
|
||||
return static_cast<const Self&>(*this);
|
||||
return static_cast<const Self&>(*this);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -331,29 +331,29 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_array_array_compression(const int* array, size_t n,
|
||||
int* dest, size_t& dest_n)
|
||||
: stream_compression_base<int_array_array_compression>(n),
|
||||
array_(array), result_size_(dest_n),
|
||||
result_(dest), result_end_(dest + dest_n)
|
||||
int* dest, size_t& dest_n)
|
||||
: stream_compression_base<int_array_array_compression>(n),
|
||||
array_(array), result_size_(dest_n),
|
||||
result_(dest), result_end_(dest + dest_n)
|
||||
{
|
||||
result_size_ = 0; // this resets dest_n.
|
||||
result_size_ = 0; // this resets dest_n.
|
||||
}
|
||||
|
||||
void push_data(unsigned int i)
|
||||
{
|
||||
assert(result_ < result_end_);
|
||||
++result_size_;
|
||||
*result_++ = static_cast<int>(i);
|
||||
assert(result_ < result_end_);
|
||||
++result_size_;
|
||||
*result_++ = static_cast<int>(i);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
array_ += offset;
|
||||
array_ += offset;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -368,7 +368,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_array_array_compress2(const int* array, size_t n,
|
||||
int* dest, size_t& dest_size)
|
||||
int* dest, size_t& dest_size)
|
||||
{
|
||||
int_array_array_compression c(array, n, dest, dest_size);
|
||||
c.run();
|
||||
|
|
@ -386,113 +386,113 @@ namespace spot
|
|||
|
||||
void run()
|
||||
{
|
||||
while (SPOT_LIKELY(self().have_comp_data()))
|
||||
{
|
||||
unsigned val = self().next_comp_data();
|
||||
while (SPOT_LIKELY(self().have_comp_data()))
|
||||
{
|
||||
unsigned val = self().next_comp_data();
|
||||
|
||||
unsigned id = val >> 28;
|
||||
switch (id)
|
||||
{
|
||||
case 0x00: // 00xx - 30 1-bit values.
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
self().write_data_at(0, !!(val & (1 << 29)));
|
||||
self().write_data_at(1, !!(val & (1 << 28)));
|
||||
self().write_data_at(2, !!(val & (1 << 27)));
|
||||
self().write_data_at(3, !!(val & (1 << 26)));
|
||||
self().write_data_at(4, !!(val & (1 << 25)));
|
||||
self().write_data_at(5, !!(val & (1 << 24)));
|
||||
self().write_data_at(6, !!(val & (1 << 23)));
|
||||
self().write_data_at(7, !!(val & (1 << 22)));
|
||||
self().write_data_at(8, !!(val & (1 << 21)));
|
||||
self().write_data_at(9, !!(val & (1 << 20)));
|
||||
self().write_data_at(10, !!(val & (1 << 19)));
|
||||
self().write_data_at(11, !!(val & (1 << 18)));
|
||||
self().write_data_at(12, !!(val & (1 << 17)));
|
||||
self().write_data_at(13, !!(val & (1 << 16)));
|
||||
self().write_data_at(14, !!(val & (1 << 15)));
|
||||
self().write_data_at(15, !!(val & (1 << 14)));
|
||||
self().write_data_at(16, !!(val & (1 << 13)));
|
||||
self().write_data_at(17, !!(val & (1 << 12)));
|
||||
self().write_data_at(18, !!(val & (1 << 11)));
|
||||
self().write_data_at(19, !!(val & (1 << 10)));
|
||||
self().write_data_at(20, !!(val & (1 << 9)));
|
||||
self().write_data_at(21, !!(val & (1 << 8)));
|
||||
self().write_data_at(22, !!(val & (1 << 7)));
|
||||
self().write_data_at(23, !!(val & (1 << 6)));
|
||||
self().write_data_at(24, !!(val & (1 << 5)));
|
||||
self().write_data_at(25, !!(val & (1 << 4)));
|
||||
self().write_data_at(26, !!(val & (1 << 3)));
|
||||
self().write_data_at(27, !!(val & (1 << 2)));
|
||||
self().write_data_at(28, !!(val & (1 << 1)));
|
||||
self().write_data_at(29, !!(val & (1 << 0)));
|
||||
self().forward(30);
|
||||
break;
|
||||
case 0x04: // 01xx - 10 3-bit values.
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
self().write_data_at(0, (val >> 27) & 0x07);
|
||||
self().write_data_at(1, (val >> 24) & 0x07);
|
||||
self().write_data_at(2, (val >> 21) & 0x07);
|
||||
self().write_data_at(3, (val >> 18) & 0x07);
|
||||
self().write_data_at(4, (val >> 15) & 0x07);
|
||||
self().write_data_at(5, (val >> 12) & 0x07);
|
||||
self().write_data_at(6, (val >> 9) & 0x07);
|
||||
self().write_data_at(7, (val >> 6) & 0x07);
|
||||
self().write_data_at(8, (val >> 3) & 0x07);
|
||||
self().write_data_at(9, (val >> 0) & 0x07);
|
||||
self().forward(10);
|
||||
break;
|
||||
case 0x08: // 10xx - 6 5-bit values.
|
||||
case 0x09:
|
||||
case 0x0A:
|
||||
case 0x0B:
|
||||
self().write_data_at(0, (val >> 25) & 0x1F);
|
||||
self().write_data_at(1, (val >> 20) & 0x1F);
|
||||
self().write_data_at(2, (val >> 15) & 0x1F);
|
||||
self().write_data_at(3, (val >> 10) & 0x1F);
|
||||
self().write_data_at(4, (val >> 5) & 0x1F);
|
||||
self().write_data_at(5, (val >> 0) & 0x1F);
|
||||
self().forward(6);
|
||||
break;
|
||||
case 0x0C: // 1100 - 4 7-bit values
|
||||
self().write_data_at(0, (val >> 21) & 0x7F);
|
||||
self().write_data_at(1, (val >> 14) & 0x7F);
|
||||
self().write_data_at(2, (val >> 7) & 0x7F);
|
||||
self().write_data_at(3, (val >> 0) & 0x7F);
|
||||
self().forward(4);
|
||||
break;
|
||||
case 0x0D: // 1101x - 3 9-bit values.
|
||||
self().write_data_at(0, (val >> 18) & 0x1FF);
|
||||
self().write_data_at(1, (val >> 9) & 0x1FF);
|
||||
self().write_data_at(2, (val >> 0) & 0x1FF);
|
||||
self().forward(3);
|
||||
break;
|
||||
case 0x0E: // 110x - 2 14-bit values.
|
||||
self().write_data_at(0, (val >> 14) & 0x3FFF);
|
||||
self().write_data_at(1, (val >> 0) & 0x3FFF);
|
||||
self().forward(2);
|
||||
break;
|
||||
case 0x0F: // 1100 - 1 28-bit value.
|
||||
self().write_data_at(0, val & 0xFFFFFFF);
|
||||
self().forward(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
unsigned id = val >> 28;
|
||||
switch (id)
|
||||
{
|
||||
case 0x00: // 00xx - 30 1-bit values.
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
self().write_data_at(0, !!(val & (1 << 29)));
|
||||
self().write_data_at(1, !!(val & (1 << 28)));
|
||||
self().write_data_at(2, !!(val & (1 << 27)));
|
||||
self().write_data_at(3, !!(val & (1 << 26)));
|
||||
self().write_data_at(4, !!(val & (1 << 25)));
|
||||
self().write_data_at(5, !!(val & (1 << 24)));
|
||||
self().write_data_at(6, !!(val & (1 << 23)));
|
||||
self().write_data_at(7, !!(val & (1 << 22)));
|
||||
self().write_data_at(8, !!(val & (1 << 21)));
|
||||
self().write_data_at(9, !!(val & (1 << 20)));
|
||||
self().write_data_at(10, !!(val & (1 << 19)));
|
||||
self().write_data_at(11, !!(val & (1 << 18)));
|
||||
self().write_data_at(12, !!(val & (1 << 17)));
|
||||
self().write_data_at(13, !!(val & (1 << 16)));
|
||||
self().write_data_at(14, !!(val & (1 << 15)));
|
||||
self().write_data_at(15, !!(val & (1 << 14)));
|
||||
self().write_data_at(16, !!(val & (1 << 13)));
|
||||
self().write_data_at(17, !!(val & (1 << 12)));
|
||||
self().write_data_at(18, !!(val & (1 << 11)));
|
||||
self().write_data_at(19, !!(val & (1 << 10)));
|
||||
self().write_data_at(20, !!(val & (1 << 9)));
|
||||
self().write_data_at(21, !!(val & (1 << 8)));
|
||||
self().write_data_at(22, !!(val & (1 << 7)));
|
||||
self().write_data_at(23, !!(val & (1 << 6)));
|
||||
self().write_data_at(24, !!(val & (1 << 5)));
|
||||
self().write_data_at(25, !!(val & (1 << 4)));
|
||||
self().write_data_at(26, !!(val & (1 << 3)));
|
||||
self().write_data_at(27, !!(val & (1 << 2)));
|
||||
self().write_data_at(28, !!(val & (1 << 1)));
|
||||
self().write_data_at(29, !!(val & (1 << 0)));
|
||||
self().forward(30);
|
||||
break;
|
||||
case 0x04: // 01xx - 10 3-bit values.
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
self().write_data_at(0, (val >> 27) & 0x07);
|
||||
self().write_data_at(1, (val >> 24) & 0x07);
|
||||
self().write_data_at(2, (val >> 21) & 0x07);
|
||||
self().write_data_at(3, (val >> 18) & 0x07);
|
||||
self().write_data_at(4, (val >> 15) & 0x07);
|
||||
self().write_data_at(5, (val >> 12) & 0x07);
|
||||
self().write_data_at(6, (val >> 9) & 0x07);
|
||||
self().write_data_at(7, (val >> 6) & 0x07);
|
||||
self().write_data_at(8, (val >> 3) & 0x07);
|
||||
self().write_data_at(9, (val >> 0) & 0x07);
|
||||
self().forward(10);
|
||||
break;
|
||||
case 0x08: // 10xx - 6 5-bit values.
|
||||
case 0x09:
|
||||
case 0x0A:
|
||||
case 0x0B:
|
||||
self().write_data_at(0, (val >> 25) & 0x1F);
|
||||
self().write_data_at(1, (val >> 20) & 0x1F);
|
||||
self().write_data_at(2, (val >> 15) & 0x1F);
|
||||
self().write_data_at(3, (val >> 10) & 0x1F);
|
||||
self().write_data_at(4, (val >> 5) & 0x1F);
|
||||
self().write_data_at(5, (val >> 0) & 0x1F);
|
||||
self().forward(6);
|
||||
break;
|
||||
case 0x0C: // 1100 - 4 7-bit values
|
||||
self().write_data_at(0, (val >> 21) & 0x7F);
|
||||
self().write_data_at(1, (val >> 14) & 0x7F);
|
||||
self().write_data_at(2, (val >> 7) & 0x7F);
|
||||
self().write_data_at(3, (val >> 0) & 0x7F);
|
||||
self().forward(4);
|
||||
break;
|
||||
case 0x0D: // 1101x - 3 9-bit values.
|
||||
self().write_data_at(0, (val >> 18) & 0x1FF);
|
||||
self().write_data_at(1, (val >> 9) & 0x1FF);
|
||||
self().write_data_at(2, (val >> 0) & 0x1FF);
|
||||
self().forward(3);
|
||||
break;
|
||||
case 0x0E: // 110x - 2 14-bit values.
|
||||
self().write_data_at(0, (val >> 14) & 0x3FFF);
|
||||
self().write_data_at(1, (val >> 0) & 0x3FFF);
|
||||
self().forward(2);
|
||||
break;
|
||||
case 0x0F: // 1100 - 1 28-bit value.
|
||||
self().write_data_at(0, val & 0xFFFFFFF);
|
||||
self().forward(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
Self& self()
|
||||
{
|
||||
return static_cast<Self&>(*this);
|
||||
return static_cast<Self&>(*this);
|
||||
}
|
||||
|
||||
const Self& self() const
|
||||
{
|
||||
return static_cast<const Self&>(*this);
|
||||
return static_cast<const Self&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -502,30 +502,30 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_array_array_decompression(const int* array,
|
||||
size_t array_size,
|
||||
int* res)
|
||||
: array_(array), n_(array_size), pos_(0), result_(res)
|
||||
size_t array_size,
|
||||
int* res)
|
||||
: array_(array), n_(array_size), pos_(0), result_(res)
|
||||
{
|
||||
}
|
||||
|
||||
void write_data_at(size_t pos, unsigned int i)
|
||||
{
|
||||
result_[pos] = i;
|
||||
result_[pos] = i;
|
||||
}
|
||||
|
||||
void forward(size_t i)
|
||||
{
|
||||
result_ += i;
|
||||
result_ += i;
|
||||
}
|
||||
|
||||
bool have_comp_data() const
|
||||
{
|
||||
return pos_ < n_;
|
||||
return pos_ < n_;
|
||||
}
|
||||
|
||||
unsigned int next_comp_data()
|
||||
{
|
||||
return array_[pos_++];
|
||||
return array_[pos_++];
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -540,7 +540,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_array_array_decompress2(const int* array, size_t array_size, int* res,
|
||||
size_t)
|
||||
size_t)
|
||||
{
|
||||
int_array_array_decompression c(array, array_size, res);
|
||||
c.run();
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace spot
|
|||
/// filled in \a dest
|
||||
SPOT_API void
|
||||
int_array_array_compress2(const int* array, size_t n,
|
||||
int* dest, size_t& dest_size);
|
||||
int* dest, size_t& dest_size);
|
||||
|
||||
/// \brief Uncompress an int array of size \a array_size into a int
|
||||
/// array of size \a size.
|
||||
|
|
@ -44,7 +44,7 @@ namespace spot
|
|||
/// \a size must be the exact expected size of uncompressed array.
|
||||
SPOT_API void
|
||||
int_array_array_decompress2(const int* array, size_t array_size,
|
||||
int* res, size_t size);
|
||||
int* res, size_t size);
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,129 +55,129 @@ namespace spot
|
|||
|
||||
public:
|
||||
stream_compression_base()
|
||||
: cur_(0), bits_left_(max_bits)
|
||||
: cur_(0), bits_left_(max_bits)
|
||||
{
|
||||
}
|
||||
|
||||
void emit(unsigned int val)
|
||||
{
|
||||
if (val == 0)
|
||||
{
|
||||
self().push_bits(0x0, 2, 0x3);
|
||||
}
|
||||
else if (val == 1)
|
||||
{
|
||||
self().push_bits(0x2, 3, 0x7);
|
||||
}
|
||||
else if (val >= 2 && val <= 5)
|
||||
{
|
||||
self().push_bits(0x3, 3, 0x7);
|
||||
self().push_bits(val - 2, 2, 0x3);
|
||||
}
|
||||
else if (val >= 6 && val <= 22)
|
||||
{
|
||||
self().push_bits(0x4, 3, 0x7);
|
||||
self().push_bits(val - 6, 4, 0xf);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(val > 22);
|
||||
self().push_bits(0x7, 3, 0x7);
|
||||
self().push_bits(val, 32, -1U);
|
||||
}
|
||||
if (val == 0)
|
||||
{
|
||||
self().push_bits(0x0, 2, 0x3);
|
||||
}
|
||||
else if (val == 1)
|
||||
{
|
||||
self().push_bits(0x2, 3, 0x7);
|
||||
}
|
||||
else if (val >= 2 && val <= 5)
|
||||
{
|
||||
self().push_bits(0x3, 3, 0x7);
|
||||
self().push_bits(val - 2, 2, 0x3);
|
||||
}
|
||||
else if (val >= 6 && val <= 22)
|
||||
{
|
||||
self().push_bits(0x4, 3, 0x7);
|
||||
self().push_bits(val - 6, 4, 0xf);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(val > 22);
|
||||
self().push_bits(0x7, 3, 0x7);
|
||||
self().push_bits(val, 32, -1U);
|
||||
}
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
unsigned int last_val = 0;
|
||||
unsigned int last_val = 0;
|
||||
|
||||
while (SPOT_LIKELY(self().have_data()))
|
||||
{
|
||||
unsigned int val = self().next_data();
|
||||
// Repeated value? Try to find more.
|
||||
if (val == last_val)
|
||||
{
|
||||
unsigned int count = 1;
|
||||
while (count < 40 && self().skip_if(val))
|
||||
++count;
|
||||
while (SPOT_LIKELY(self().have_data()))
|
||||
{
|
||||
unsigned int val = self().next_data();
|
||||
// Repeated value? Try to find more.
|
||||
if (val == last_val)
|
||||
{
|
||||
unsigned int count = 1;
|
||||
while (count < 40 && self().skip_if(val))
|
||||
++count;
|
||||
|
||||
if ((val == 0 && count < 3) || (val == 1 && count == 1))
|
||||
{
|
||||
// it is more efficient to emit 0 once or twice directly
|
||||
// (e.g., 00 00 vs. 011 11)
|
||||
// for value 1, repetition is worthwhile for count > 1
|
||||
// (e.g., 010 010 vs. 011 00)
|
||||
while (count--)
|
||||
emit(val);
|
||||
}
|
||||
else if (count < 9)
|
||||
{
|
||||
self().push_bits(0x5, 3, 0x7);
|
||||
self().push_bits(count - 1, 3, 0x7);
|
||||
}
|
||||
else
|
||||
{
|
||||
self().push_bits(0x6, 3, 0x7);
|
||||
self().push_bits(count - 9, 5, 0x1f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
emit(val);
|
||||
last_val = val;
|
||||
}
|
||||
}
|
||||
flush();
|
||||
if ((val == 0 && count < 3) || (val == 1 && count == 1))
|
||||
{
|
||||
// it is more efficient to emit 0 once or twice directly
|
||||
// (e.g., 00 00 vs. 011 11)
|
||||
// for value 1, repetition is worthwhile for count > 1
|
||||
// (e.g., 010 010 vs. 011 00)
|
||||
while (count--)
|
||||
emit(val);
|
||||
}
|
||||
else if (count < 9)
|
||||
{
|
||||
self().push_bits(0x5, 3, 0x7);
|
||||
self().push_bits(count - 1, 3, 0x7);
|
||||
}
|
||||
else
|
||||
{
|
||||
self().push_bits(0x6, 3, 0x7);
|
||||
self().push_bits(count - 9, 5, 0x1f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
emit(val);
|
||||
last_val = val;
|
||||
}
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
// This version assumes there is at least n bits free in cur_.
|
||||
void
|
||||
push_bits_unchecked(unsigned int bits, unsigned int n, unsigned int mask)
|
||||
{
|
||||
cur_ <<= n;
|
||||
cur_ |= (bits & mask);
|
||||
if (SPOT_LIKELY(bits_left_ -= n))
|
||||
return;
|
||||
cur_ <<= n;
|
||||
cur_ |= (bits & mask);
|
||||
if (SPOT_LIKELY(bits_left_ -= n))
|
||||
return;
|
||||
|
||||
self().push_data(cur_);
|
||||
cur_ = 0;
|
||||
bits_left_ = max_bits;
|
||||
self().push_data(cur_);
|
||||
cur_ = 0;
|
||||
bits_left_ = max_bits;
|
||||
}
|
||||
|
||||
void
|
||||
push_bits(unsigned int bits, unsigned int n, unsigned int mask)
|
||||
{
|
||||
if (SPOT_LIKELY(n <= bits_left_))
|
||||
{
|
||||
push_bits_unchecked(bits, n, mask);
|
||||
return;
|
||||
}
|
||||
if (SPOT_LIKELY(n <= bits_left_))
|
||||
{
|
||||
push_bits_unchecked(bits, n, mask);
|
||||
return;
|
||||
}
|
||||
|
||||
// bits_left_ < n
|
||||
// bits_left_ < n
|
||||
|
||||
unsigned int right_bit_count = n - bits_left_;
|
||||
unsigned int left = bits >> right_bit_count;
|
||||
push_bits_unchecked(left, bits_left_, (1 << bits_left_) - 1);
|
||||
push_bits_unchecked(bits, right_bit_count, (1 << right_bit_count) - 1);
|
||||
unsigned int right_bit_count = n - bits_left_;
|
||||
unsigned int left = bits >> right_bit_count;
|
||||
push_bits_unchecked(left, bits_left_, (1 << bits_left_) - 1);
|
||||
push_bits_unchecked(bits, right_bit_count, (1 << right_bit_count) - 1);
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
if (bits_left_ == max_bits)
|
||||
return;
|
||||
cur_ <<= bits_left_;
|
||||
self().push_data(cur_);
|
||||
if (bits_left_ == max_bits)
|
||||
return;
|
||||
cur_ <<= bits_left_;
|
||||
self().push_data(cur_);
|
||||
}
|
||||
|
||||
protected:
|
||||
Self& self()
|
||||
{
|
||||
return static_cast<Self&>(*this);
|
||||
return static_cast<Self&>(*this);
|
||||
}
|
||||
|
||||
const Self& self() const
|
||||
{
|
||||
return static_cast<const Self&>(*this);
|
||||
return static_cast<const Self&>(*this);
|
||||
}
|
||||
|
||||
unsigned int cur_;
|
||||
|
|
@ -189,41 +189,41 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_array_vector_compression(const int* array, size_t n)
|
||||
: array_(array), n_(n), pos_(0), result_(new std::vector<unsigned int>)
|
||||
: array_(array), n_(n), pos_(0), result_(new std::vector<unsigned int>)
|
||||
{
|
||||
}
|
||||
|
||||
void push_data(unsigned int i)
|
||||
{
|
||||
result_->push_back(i);
|
||||
result_->push_back(i);
|
||||
}
|
||||
|
||||
const std::vector<unsigned int>*
|
||||
result() const
|
||||
{
|
||||
return result_;
|
||||
return result_;
|
||||
}
|
||||
|
||||
bool have_data() const
|
||||
{
|
||||
return pos_ < n_;
|
||||
return pos_ < n_;
|
||||
}
|
||||
|
||||
unsigned int next_data()
|
||||
{
|
||||
return static_cast<unsigned int>(array_[pos_++]);
|
||||
return static_cast<unsigned int>(array_[pos_++]);
|
||||
}
|
||||
|
||||
bool skip_if(unsigned int val)
|
||||
{
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
|
||||
if (static_cast<unsigned int>(array_[pos_]) != val)
|
||||
return false;
|
||||
if (static_cast<unsigned int>(array_[pos_]) != val)
|
||||
return false;
|
||||
|
||||
++pos_;
|
||||
return true;
|
||||
++pos_;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -238,36 +238,36 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_vector_vector_compression(const std::vector<int>& input,
|
||||
std::vector<unsigned int>& output)
|
||||
: input_(input), pos_(input.begin()), end_(input.end()), output_(output)
|
||||
std::vector<unsigned int>& output)
|
||||
: input_(input), pos_(input.begin()), end_(input.end()), output_(output)
|
||||
{
|
||||
}
|
||||
|
||||
void push_data(unsigned int i)
|
||||
{
|
||||
output_.push_back(i);
|
||||
output_.push_back(i);
|
||||
}
|
||||
|
||||
bool have_data() const
|
||||
{
|
||||
return pos_ < end_;
|
||||
return pos_ < end_;
|
||||
}
|
||||
|
||||
unsigned int next_data()
|
||||
{
|
||||
return static_cast<unsigned int>(*pos_++);
|
||||
return static_cast<unsigned int>(*pos_++);
|
||||
}
|
||||
|
||||
bool skip_if(unsigned int val)
|
||||
{
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
|
||||
if (static_cast<unsigned int>(*pos_) != val)
|
||||
return false;
|
||||
if (static_cast<unsigned int>(*pos_) != val)
|
||||
return false;
|
||||
|
||||
++pos_;
|
||||
return true;
|
||||
++pos_;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -282,40 +282,40 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_array_array_compression(const int* array, size_t n,
|
||||
int* dest, size_t& dest_n)
|
||||
: array_(array), n_(n), pos_(0),
|
||||
result_size_(dest_n), result_(dest), result_end_(dest + dest_n)
|
||||
int* dest, size_t& dest_n)
|
||||
: array_(array), n_(n), pos_(0),
|
||||
result_size_(dest_n), result_(dest), result_end_(dest + dest_n)
|
||||
{
|
||||
result_size_ = 0; // this resets dest_n.
|
||||
result_size_ = 0; // this resets dest_n.
|
||||
}
|
||||
|
||||
void push_data(unsigned int i)
|
||||
{
|
||||
assert(result_ < result_end_);
|
||||
++result_size_;
|
||||
*result_++ = static_cast<int>(i);
|
||||
assert(result_ < result_end_);
|
||||
++result_size_;
|
||||
*result_++ = static_cast<int>(i);
|
||||
}
|
||||
|
||||
bool have_data() const
|
||||
{
|
||||
return pos_ < n_;
|
||||
return pos_ < n_;
|
||||
}
|
||||
|
||||
unsigned int next_data()
|
||||
{
|
||||
return static_cast<unsigned int>(array_[pos_++]);
|
||||
return static_cast<unsigned int>(array_[pos_++]);
|
||||
}
|
||||
|
||||
bool skip_if(unsigned int val)
|
||||
{
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
if (SPOT_UNLIKELY(!have_data()))
|
||||
return false;
|
||||
|
||||
if (static_cast<unsigned int>(array_[pos_]) != val)
|
||||
return false;
|
||||
if (static_cast<unsigned int>(array_[pos_]) != val)
|
||||
return false;
|
||||
|
||||
++pos_;
|
||||
return true;
|
||||
++pos_;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -330,7 +330,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_vector_vector_compress(const std::vector<int>& input,
|
||||
std::vector<unsigned>& output)
|
||||
std::vector<unsigned>& output)
|
||||
{
|
||||
int_vector_vector_compression c(input, output);
|
||||
c.run();
|
||||
|
|
@ -346,7 +346,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_array_array_compress(const int* array, size_t n,
|
||||
int* dest, size_t& dest_size)
|
||||
int* dest, size_t& dest_size)
|
||||
{
|
||||
int_array_array_compression c(array, n, dest, dest_size);
|
||||
c.run();
|
||||
|
|
@ -365,154 +365,154 @@ namespace spot
|
|||
public:
|
||||
void refill()
|
||||
{
|
||||
if (SPOT_UNLIKELY(look_bits_ == 0))
|
||||
{
|
||||
look_bits_ = max_bits;
|
||||
look_ = buffer_;
|
||||
if (SPOT_UNLIKELY(look_bits_ == 0))
|
||||
{
|
||||
look_bits_ = max_bits;
|
||||
look_ = buffer_;
|
||||
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
buffer_ = self().next_comp_data();
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
buffer_ = self().next_comp_data();
|
||||
|
||||
if (SPOT_LIKELY(buffer_bits_ != max_bits))
|
||||
{
|
||||
unsigned int fill_size = max_bits - buffer_bits_;
|
||||
look_ <<= fill_size;
|
||||
look_ |= buffer_ >> buffer_bits_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int fill_size = max_bits - look_bits_;
|
||||
if (fill_size > buffer_bits_)
|
||||
fill_size = buffer_bits_;
|
||||
if (SPOT_LIKELY(buffer_bits_ != max_bits))
|
||||
{
|
||||
unsigned int fill_size = max_bits - buffer_bits_;
|
||||
look_ <<= fill_size;
|
||||
look_ |= buffer_ >> buffer_bits_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int fill_size = max_bits - look_bits_;
|
||||
if (fill_size > buffer_bits_)
|
||||
fill_size = buffer_bits_;
|
||||
|
||||
look_ <<= fill_size;
|
||||
buffer_bits_ -= fill_size;
|
||||
look_ |= (buffer_ >> buffer_bits_) & ((1 << fill_size) - 1);
|
||||
look_bits_ += fill_size;
|
||||
look_ <<= fill_size;
|
||||
buffer_bits_ -= fill_size;
|
||||
look_ |= (buffer_ >> buffer_bits_) & ((1 << fill_size) - 1);
|
||||
look_bits_ += fill_size;
|
||||
|
||||
if (buffer_bits_ == 0)
|
||||
{
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
buffer_ = self().next_comp_data();
|
||||
if (buffer_bits_ == 0)
|
||||
{
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
buffer_ = self().next_comp_data();
|
||||
|
||||
unsigned int left = max_bits - look_bits_;
|
||||
if (left != 0)
|
||||
{
|
||||
look_ <<= left;
|
||||
look_ |= buffer_ >> look_bits_;
|
||||
buffer_bits_ = look_bits_;
|
||||
look_bits_ = max_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_bits_ = max_bits;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int left = max_bits - look_bits_;
|
||||
if (left != 0)
|
||||
{
|
||||
look_ <<= left;
|
||||
look_ |= buffer_ >> look_bits_;
|
||||
buffer_bits_ = look_bits_;
|
||||
look_bits_ = max_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_bits_ = max_bits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int look_n_bits(unsigned int n)
|
||||
{
|
||||
if (SPOT_UNLIKELY(look_bits_ < n))
|
||||
refill();
|
||||
assert(n <= look_bits_);
|
||||
return (look_ >> (look_bits_ - n)) & ((1 << n) - 1);
|
||||
if (SPOT_UNLIKELY(look_bits_ < n))
|
||||
refill();
|
||||
assert(n <= look_bits_);
|
||||
return (look_ >> (look_bits_ - n)) & ((1 << n) - 1);
|
||||
}
|
||||
|
||||
void skip_n_bits(unsigned int n)
|
||||
{
|
||||
assert (n <= look_bits_);
|
||||
look_bits_ -= n;
|
||||
assert (n <= look_bits_);
|
||||
look_bits_ -= n;
|
||||
}
|
||||
|
||||
unsigned int get_n_bits(unsigned int n)
|
||||
{
|
||||
if (SPOT_UNLIKELY(look_bits_ < n))
|
||||
refill();
|
||||
look_bits_ -= n;
|
||||
return (look_ >> look_bits_) & ((1 << n) - 1);
|
||||
if (SPOT_UNLIKELY(look_bits_ < n))
|
||||
refill();
|
||||
look_bits_ -= n;
|
||||
return (look_ >> look_bits_) & ((1 << n) - 1);
|
||||
}
|
||||
|
||||
unsigned int get_32_bits()
|
||||
{
|
||||
// std::cerr << "get_32" << std::endl;
|
||||
if (SPOT_LIKELY(look_bits_ < 32))
|
||||
refill();
|
||||
unsigned int val = look_;
|
||||
look_bits_ = 0;
|
||||
refill();
|
||||
return val;
|
||||
// std::cerr << "get_32" << std::endl;
|
||||
if (SPOT_LIKELY(look_bits_ < 32))
|
||||
refill();
|
||||
unsigned int val = look_;
|
||||
look_bits_ = 0;
|
||||
refill();
|
||||
return val;
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
if (SPOT_UNLIKELY(!self().have_comp_data()))
|
||||
return;
|
||||
if (SPOT_UNLIKELY(!self().have_comp_data()))
|
||||
return;
|
||||
|
||||
look_ = self().next_comp_data();
|
||||
look_bits_ = max_bits;
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
{
|
||||
buffer_ = self().next_comp_data();
|
||||
buffer_bits_ = max_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_ = 0;
|
||||
buffer_bits_ = 0;
|
||||
}
|
||||
look_ = self().next_comp_data();
|
||||
look_bits_ = max_bits;
|
||||
if (SPOT_LIKELY(self().have_comp_data()))
|
||||
{
|
||||
buffer_ = self().next_comp_data();
|
||||
buffer_bits_ = max_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_ = 0;
|
||||
buffer_bits_ = 0;
|
||||
}
|
||||
|
||||
while (SPOT_LIKELY(!self().complete()))
|
||||
{
|
||||
unsigned int token = look_n_bits(3);
|
||||
switch (token)
|
||||
{
|
||||
case 0x0: // 00[0]
|
||||
case 0x1: // 00[1]
|
||||
skip_n_bits(2);
|
||||
self().push_data(0);
|
||||
break;
|
||||
case 0x2: // 010
|
||||
skip_n_bits(3);
|
||||
self().push_data(1);
|
||||
break;
|
||||
case 0x3: // 011
|
||||
skip_n_bits(3);
|
||||
self().push_data(2 + get_n_bits(2));
|
||||
break;
|
||||
case 0x4: // 100
|
||||
skip_n_bits(3);
|
||||
self().push_data(6 + get_n_bits(4));
|
||||
break;
|
||||
case 0x5: // 101
|
||||
skip_n_bits(3);
|
||||
self().repeat(1 + get_n_bits(3));
|
||||
break;
|
||||
case 0x6: // 110
|
||||
skip_n_bits(3);
|
||||
self().repeat(9 + get_n_bits(5));
|
||||
break;
|
||||
case 0x7: // 111
|
||||
skip_n_bits(3);
|
||||
self().push_data(get_32_bits());
|
||||
break;
|
||||
default:
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
while (SPOT_LIKELY(!self().complete()))
|
||||
{
|
||||
unsigned int token = look_n_bits(3);
|
||||
switch (token)
|
||||
{
|
||||
case 0x0: // 00[0]
|
||||
case 0x1: // 00[1]
|
||||
skip_n_bits(2);
|
||||
self().push_data(0);
|
||||
break;
|
||||
case 0x2: // 010
|
||||
skip_n_bits(3);
|
||||
self().push_data(1);
|
||||
break;
|
||||
case 0x3: // 011
|
||||
skip_n_bits(3);
|
||||
self().push_data(2 + get_n_bits(2));
|
||||
break;
|
||||
case 0x4: // 100
|
||||
skip_n_bits(3);
|
||||
self().push_data(6 + get_n_bits(4));
|
||||
break;
|
||||
case 0x5: // 101
|
||||
skip_n_bits(3);
|
||||
self().repeat(1 + get_n_bits(3));
|
||||
break;
|
||||
case 0x6: // 110
|
||||
skip_n_bits(3);
|
||||
self().repeat(9 + get_n_bits(5));
|
||||
break;
|
||||
case 0x7: // 111
|
||||
skip_n_bits(3);
|
||||
self().push_data(get_32_bits());
|
||||
break;
|
||||
default:
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
Self& self()
|
||||
{
|
||||
return static_cast<Self&>(*this);
|
||||
return static_cast<Self&>(*this);
|
||||
}
|
||||
|
||||
const Self& self() const
|
||||
{
|
||||
return static_cast<const Self&>(*this);
|
||||
return static_cast<const Self&>(*this);
|
||||
}
|
||||
|
||||
unsigned int look_;
|
||||
|
|
@ -526,41 +526,41 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_vector_vector_decompression(const std::vector<unsigned int>& array,
|
||||
std::vector<int>& res, size_t size)
|
||||
: prev_(0), array_(array),
|
||||
pos_(array.begin()), end_(array.end()),
|
||||
result_(res), size_(size)
|
||||
std::vector<int>& res, size_t size)
|
||||
: prev_(0), array_(array),
|
||||
pos_(array.begin()), end_(array.end()),
|
||||
result_(res), size_(size)
|
||||
{
|
||||
result_.reserve(size);
|
||||
result_.reserve(size);
|
||||
}
|
||||
|
||||
bool complete() const
|
||||
{
|
||||
return size_ == 0;
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
void push_data(int i)
|
||||
{
|
||||
prev_ = i;
|
||||
result_.push_back(i);
|
||||
--size_;
|
||||
prev_ = i;
|
||||
result_.push_back(i);
|
||||
--size_;
|
||||
}
|
||||
|
||||
void repeat(unsigned int i)
|
||||
{
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
result_.push_back(prev_);
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
result_.push_back(prev_);
|
||||
}
|
||||
|
||||
bool have_comp_data() const
|
||||
{
|
||||
return pos_ != end_;
|
||||
return pos_ != end_;
|
||||
}
|
||||
|
||||
unsigned int next_comp_data()
|
||||
{
|
||||
return *pos_++;
|
||||
return *pos_++;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -577,40 +577,40 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_vector_array_decompression(const std::vector<unsigned int>* array,
|
||||
int* res,
|
||||
size_t size)
|
||||
: prev_(0), array_(array), n_(array->size()), pos_(0), result_(res),
|
||||
size_(size)
|
||||
int* res,
|
||||
size_t size)
|
||||
: prev_(0), array_(array), n_(array->size()), pos_(0), result_(res),
|
||||
size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
bool complete() const
|
||||
{
|
||||
return size_ == 0;
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
void push_data(int i)
|
||||
{
|
||||
prev_ = i;
|
||||
*result_++ = i;
|
||||
--size_;
|
||||
prev_ = i;
|
||||
*result_++ = i;
|
||||
--size_;
|
||||
}
|
||||
|
||||
void repeat(unsigned int i)
|
||||
{
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
*result_++ = prev_;
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
*result_++ = prev_;
|
||||
}
|
||||
|
||||
bool have_comp_data() const
|
||||
{
|
||||
return pos_ < n_;
|
||||
return pos_ < n_;
|
||||
}
|
||||
|
||||
unsigned int next_comp_data()
|
||||
{
|
||||
return (*array_)[pos_++];
|
||||
return (*array_)[pos_++];
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -627,41 +627,41 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
int_array_array_decompression(const int* array,
|
||||
size_t array_size,
|
||||
int* res,
|
||||
size_t size)
|
||||
: prev_(0), array_(array), n_(array_size), pos_(0), result_(res),
|
||||
size_(size)
|
||||
size_t array_size,
|
||||
int* res,
|
||||
size_t size)
|
||||
: prev_(0), array_(array), n_(array_size), pos_(0), result_(res),
|
||||
size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
bool complete() const
|
||||
{
|
||||
return size_ == 0;
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
void push_data(int i)
|
||||
{
|
||||
prev_ = i;
|
||||
*result_++ = i;
|
||||
--size_;
|
||||
prev_ = i;
|
||||
*result_++ = i;
|
||||
--size_;
|
||||
}
|
||||
|
||||
void repeat(unsigned int i)
|
||||
{
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
*result_++ = prev_;
|
||||
size_ -= i;
|
||||
while (i--)
|
||||
*result_++ = prev_;
|
||||
}
|
||||
|
||||
bool have_comp_data() const
|
||||
{
|
||||
return pos_ < n_;
|
||||
return pos_ < n_;
|
||||
}
|
||||
|
||||
unsigned int next_comp_data()
|
||||
{
|
||||
return array_[pos_++];
|
||||
return array_[pos_++];
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -677,7 +677,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_vector_vector_decompress(const std::vector<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);
|
||||
c.run();
|
||||
|
|
@ -685,7 +685,7 @@ namespace spot
|
|||
|
||||
void
|
||||
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);
|
||||
c.run();
|
||||
|
|
@ -693,7 +693,7 @@ namespace spot
|
|||
|
||||
void
|
||||
int_array_array_decompress(const int* array, size_t array_size,
|
||||
int* res, size_t size)
|
||||
int* res, size_t size)
|
||||
{
|
||||
int_array_array_decompression c(array, array_size, res, size);
|
||||
c.run();
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace spot
|
|||
/// Compress an int vector into a vector of unsigned int.
|
||||
SPOT_API void
|
||||
int_vector_vector_compress(const std::vector<int>& input,
|
||||
std::vector<unsigned int>& output);
|
||||
std::vector<unsigned int>& output);
|
||||
|
||||
/// \brief Uncompress a vector of unsigned int into a vector of
|
||||
/// size \a size.
|
||||
|
|
@ -39,7 +39,7 @@ namespace spot
|
|||
/// \a size must be the exact expected size of uncompressed array.
|
||||
SPOT_API void
|
||||
int_vector_vector_decompress(const std::vector<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.
|
||||
SPOT_API const std::vector<unsigned int>*
|
||||
|
|
@ -51,7 +51,7 @@ namespace spot
|
|||
/// \a size must be the exact expected size of uncompressed array.
|
||||
SPOT_API void
|
||||
int_vector_array_decompress(const std::vector<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.
|
||||
///
|
||||
|
|
@ -61,7 +61,7 @@ namespace spot
|
|||
/// filled in \a dest
|
||||
SPOT_API void
|
||||
int_array_array_compress(const int* array, size_t n,
|
||||
int* dest, size_t& dest_size);
|
||||
int* dest, size_t& dest_size);
|
||||
|
||||
/// \brief Uncompress an int array of size \a array_size into a int
|
||||
/// array of size \a size.
|
||||
|
|
@ -69,7 +69,7 @@ namespace spot
|
|||
/// \a size must be the exact expected size of uncompressed array.
|
||||
SPOT_API void
|
||||
int_array_array_decompress(const int* array, size_t array_size,
|
||||
int* res, size_t size);
|
||||
int* res, size_t size);
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,8 +157,8 @@ namespace spot
|
|||
position last = loc.end - 1;
|
||||
ostr << loc.begin;
|
||||
if (last.filename
|
||||
&& (!loc.begin.filename
|
||||
|| *loc.begin.filename != *last.filename))
|
||||
&& (!loc.begin.filename
|
||||
|| *loc.begin.filename != *last.filename))
|
||||
ostr << '-' << last;
|
||||
else if (loc.begin.line != last.line)
|
||||
ostr << '-' << last.line << '.' << last.column;
|
||||
|
|
|
|||
|
|
@ -51,12 +51,12 @@ namespace spot
|
|||
{
|
||||
if (input_min == input_max)
|
||||
{
|
||||
cube_.push(bdd_satprefix(input_min));
|
||||
input_max = input_min;
|
||||
cube_.push(bdd_satprefix(input_min));
|
||||
input_max = input_min;
|
||||
}
|
||||
else
|
||||
{
|
||||
cube_.push(bddtrue);
|
||||
cube_.push(bddtrue);
|
||||
}
|
||||
bdd common = input_min & input_max;
|
||||
todo_.emplace(input_min, input_max, bdd_support(common));
|
||||
|
|
@ -67,110 +67,110 @@ namespace spot
|
|||
{
|
||||
while (!todo_.empty())
|
||||
{
|
||||
local_vars& l = todo_.top();
|
||||
switch (l.step)
|
||||
{
|
||||
case local_vars::FirstStep:
|
||||
next_var:
|
||||
{
|
||||
if (l.f_min == bddfalse)
|
||||
{
|
||||
ret_ = bddfalse;
|
||||
todo_.pop();
|
||||
continue;
|
||||
}
|
||||
if (l.vars == bddtrue || l.f_max == bddtrue)
|
||||
{
|
||||
ret_ = l.f_max;
|
||||
todo_.pop();
|
||||
return cube_.top() & ret_;
|
||||
}
|
||||
assert(l.vars != bddfalse);
|
||||
local_vars& l = todo_.top();
|
||||
switch (l.step)
|
||||
{
|
||||
case local_vars::FirstStep:
|
||||
next_var:
|
||||
{
|
||||
if (l.f_min == bddfalse)
|
||||
{
|
||||
ret_ = bddfalse;
|
||||
todo_.pop();
|
||||
continue;
|
||||
}
|
||||
if (l.vars == bddtrue || l.f_max == bddtrue)
|
||||
{
|
||||
ret_ = l.f_max;
|
||||
todo_.pop();
|
||||
return cube_.top() & ret_;
|
||||
}
|
||||
assert(l.vars != bddfalse);
|
||||
|
||||
// Pick the first variable in VARS that is used by F_MIN
|
||||
// or F_MAX. We know that VARS, F_MIN or F_MAX are not
|
||||
// constants (bddtrue or bddfalse) because one of the
|
||||
// two above `if' would have matched; so it's ok to call
|
||||
// bdd_var().
|
||||
int v = bdd_var(l.vars);
|
||||
l.vars = bdd_high(l.vars);
|
||||
int v_min = bdd_var(l.f_min);
|
||||
int v_max = bdd_var(l.f_max);
|
||||
if (v < v_min && v < v_max)
|
||||
// Do not use a while() for this goto, because we want
|
||||
// `continue' to be relative to the outermost while().
|
||||
goto next_var;
|
||||
// Pick the first variable in VARS that is used by F_MIN
|
||||
// or F_MAX. We know that VARS, F_MIN or F_MAX are not
|
||||
// constants (bddtrue or bddfalse) because one of the
|
||||
// two above `if' would have matched; so it's ok to call
|
||||
// bdd_var().
|
||||
int v = bdd_var(l.vars);
|
||||
l.vars = bdd_high(l.vars);
|
||||
int v_min = bdd_var(l.f_min);
|
||||
int v_max = bdd_var(l.f_max);
|
||||
if (v < v_min && v < v_max)
|
||||
// Do not use a while() for this goto, because we want
|
||||
// `continue' to be relative to the outermost while().
|
||||
goto next_var;
|
||||
|
||||
l.step = local_vars::SecondStep;
|
||||
l.step = local_vars::SecondStep;
|
||||
|
||||
bdd v0 = bdd_nithvar(v);
|
||||
l.v1 = bdd_ithvar(v);
|
||||
bdd v0 = bdd_nithvar(v);
|
||||
l.v1 = bdd_ithvar(v);
|
||||
|
||||
// All the following should be equivalent to
|
||||
// f0_min = bdd_restrict(f_min, v0);
|
||||
// f0_max = bdd_restrict(f_max, v0);
|
||||
// f1_min = bdd_restrict(f_min, v1);
|
||||
// f1_max = bdd_restrict(f_max, v1);
|
||||
// but we try to avoid bdd_restrict when possible.
|
||||
if (v == v_min)
|
||||
{
|
||||
l.f0_min = bdd_low(l.f_min);
|
||||
l.f1_min = bdd_high(l.f_min);
|
||||
}
|
||||
else if (v_min < v)
|
||||
{
|
||||
l.f0_min = bdd_restrict(l.f_min, v0);
|
||||
l.f1_min = bdd_restrict(l.f_min, l.v1);
|
||||
}
|
||||
else
|
||||
{
|
||||
l.f1_min = l.f0_min = l.f_min;
|
||||
}
|
||||
if (v == v_max)
|
||||
{
|
||||
l.f0_max = bdd_low(l.f_max);
|
||||
l.f1_max = bdd_high(l.f_max);
|
||||
}
|
||||
else if (v_max < v)
|
||||
{
|
||||
l.f0_max = bdd_restrict(l.f_max, v0);
|
||||
l.f1_max = bdd_restrict(l.f_max, l.v1);
|
||||
}
|
||||
else
|
||||
{
|
||||
l.f1_max = l.f0_max = l.f_max;
|
||||
}
|
||||
// All the following should be equivalent to
|
||||
// f0_min = bdd_restrict(f_min, v0);
|
||||
// f0_max = bdd_restrict(f_max, v0);
|
||||
// f1_min = bdd_restrict(f_min, v1);
|
||||
// f1_max = bdd_restrict(f_max, v1);
|
||||
// but we try to avoid bdd_restrict when possible.
|
||||
if (v == v_min)
|
||||
{
|
||||
l.f0_min = bdd_low(l.f_min);
|
||||
l.f1_min = bdd_high(l.f_min);
|
||||
}
|
||||
else if (v_min < v)
|
||||
{
|
||||
l.f0_min = bdd_restrict(l.f_min, v0);
|
||||
l.f1_min = bdd_restrict(l.f_min, l.v1);
|
||||
}
|
||||
else
|
||||
{
|
||||
l.f1_min = l.f0_min = l.f_min;
|
||||
}
|
||||
if (v == v_max)
|
||||
{
|
||||
l.f0_max = bdd_low(l.f_max);
|
||||
l.f1_max = bdd_high(l.f_max);
|
||||
}
|
||||
else if (v_max < v)
|
||||
{
|
||||
l.f0_max = bdd_restrict(l.f_max, v0);
|
||||
l.f1_max = bdd_restrict(l.f_max, l.v1);
|
||||
}
|
||||
else
|
||||
{
|
||||
l.f1_max = l.f0_max = l.f_max;
|
||||
}
|
||||
|
||||
cube_.push(cube_.top() & v0);
|
||||
todo_.emplace(l.f0_min - l.f1_max, l.f0_max, l.vars);
|
||||
}
|
||||
continue;
|
||||
cube_.push(cube_.top() & v0);
|
||||
todo_.emplace(l.f0_min - l.f1_max, l.f0_max, l.vars);
|
||||
}
|
||||
continue;
|
||||
|
||||
case local_vars::SecondStep:
|
||||
l.step = local_vars::ThirdStep;
|
||||
l.g0 = ret_;
|
||||
cube_.pop();
|
||||
cube_.push(cube_.top() & l.v1);
|
||||
todo_.emplace(l.f1_min - l.f0_max, l.f1_max, l.vars);
|
||||
continue;
|
||||
case local_vars::SecondStep:
|
||||
l.step = local_vars::ThirdStep;
|
||||
l.g0 = ret_;
|
||||
cube_.pop();
|
||||
cube_.push(cube_.top() & l.v1);
|
||||
todo_.emplace(l.f1_min - l.f0_max, l.f1_max, l.vars);
|
||||
continue;
|
||||
|
||||
case local_vars::ThirdStep:
|
||||
l.step = local_vars::FourthStep;
|
||||
l.g1 = ret_;
|
||||
cube_.pop();
|
||||
{
|
||||
bdd fs_max = l.f0_max & l.f1_max;
|
||||
bdd fs_min = fs_max & ((l.f0_min - l.g0) | (l.f1_min - l.g1));
|
||||
todo_.emplace(fs_min, fs_max, l.vars);
|
||||
}
|
||||
continue;
|
||||
case local_vars::ThirdStep:
|
||||
l.step = local_vars::FourthStep;
|
||||
l.g1 = ret_;
|
||||
cube_.pop();
|
||||
{
|
||||
bdd fs_max = l.f0_max & l.f1_max;
|
||||
bdd fs_min = fs_max & ((l.f0_min - l.g0) | (l.f1_min - l.g1));
|
||||
todo_.emplace(fs_min, fs_max, l.vars);
|
||||
}
|
||||
continue;
|
||||
|
||||
case local_vars::FourthStep:
|
||||
ret_ |= (l.g0 - l.v1) | (l.g1 & l.v1);
|
||||
todo_.pop();
|
||||
continue;
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
case local_vars::FourthStep:
|
||||
ret_ |= (l.g0 - l.v1) | (l.g1 & l.v1);
|
||||
todo_.pop();
|
||||
continue;
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
return bddfalse;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ namespace spot
|
|||
bdd f1_min, f1_max;
|
||||
bdd g0, g1;
|
||||
local_vars(bdd f_min, bdd f_max, bdd vars)
|
||||
: f_min(f_min), f_max(f_max), step(FirstStep), vars(vars) {}
|
||||
: f_min(f_min), f_max(f_max), step(FirstStep), vars(vars) {}
|
||||
};
|
||||
std::stack<local_vars> todo_;
|
||||
std::stack<bdd> cube_;
|
||||
|
|
|
|||
|
|
@ -43,17 +43,17 @@ namespace spot
|
|||
~multiple_size_pool()
|
||||
{
|
||||
while (chunklist_)
|
||||
{
|
||||
chunk_* prev = chunklist_->prev;
|
||||
free(chunklist_);
|
||||
chunklist_ = prev;
|
||||
}
|
||||
{
|
||||
chunk_* prev = chunklist_->prev;
|
||||
free(chunklist_);
|
||||
chunklist_ = prev;
|
||||
}
|
||||
}
|
||||
|
||||
size_t fixsize(size_t size) const
|
||||
{
|
||||
if (size < sizeof(block_))
|
||||
size = sizeof(block_);
|
||||
size = sizeof(block_);
|
||||
|
||||
return (size + alignment_ - 1) & ~(alignment_ - 1);
|
||||
}
|
||||
|
|
@ -67,28 +67,28 @@ namespace spot
|
|||
block_*& f = freelist_[size];
|
||||
// If we have free blocks available, return the first one.
|
||||
if (f)
|
||||
{
|
||||
block_* first = f;
|
||||
f = f->next;
|
||||
return first;
|
||||
}
|
||||
{
|
||||
block_* first = f;
|
||||
f = f->next;
|
||||
return first;
|
||||
}
|
||||
|
||||
// Else, create a block out of the last chunk of allocated
|
||||
// memory.
|
||||
|
||||
// If all the last chunk has been used, allocate one more.
|
||||
if (free_start_ + size > free_end_)
|
||||
{
|
||||
const size_t requested = (size > 128 ? size : 128) * 8192 - 64;
|
||||
chunk_* c = reinterpret_cast<chunk_*>(malloc(requested));
|
||||
if (!c)
|
||||
throw std::bad_alloc();
|
||||
c->prev = chunklist_;
|
||||
chunklist_ = c;
|
||||
{
|
||||
const size_t requested = (size > 128 ? size : 128) * 8192 - 64;
|
||||
chunk_* c = reinterpret_cast<chunk_*>(malloc(requested));
|
||||
if (!c)
|
||||
throw std::bad_alloc();
|
||||
c->prev = chunklist_;
|
||||
chunklist_ = c;
|
||||
|
||||
free_start_ = c->data_ + size;
|
||||
free_end_ = c->data_ + requested;
|
||||
}
|
||||
free_start_ = c->data_ + size;
|
||||
free_end_ = c->data_ + requested;
|
||||
}
|
||||
|
||||
void* res = free_start_;
|
||||
free_start_ += size;
|
||||
|
|
|
|||
|
|
@ -33,96 +33,96 @@ namespace spot
|
|||
{
|
||||
while (*options)
|
||||
{
|
||||
// Skip leading separators.
|
||||
while (*options && strchr(" \t\n,;", *options))
|
||||
++options;
|
||||
// Skip leading separators.
|
||||
while (*options && strchr(" \t\n,;", *options))
|
||||
++options;
|
||||
|
||||
// `!foo' is a shorthand for `foo=0'.
|
||||
const char* negated = nullptr;
|
||||
if (*options == '!')
|
||||
{
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
negated = options++;
|
||||
}
|
||||
// `!foo' is a shorthand for `foo=0'.
|
||||
const char* negated = nullptr;
|
||||
if (*options == '!')
|
||||
{
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
negated = options++;
|
||||
}
|
||||
|
||||
if (!*options)
|
||||
{
|
||||
if (negated)
|
||||
return negated;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!*options)
|
||||
{
|
||||
if (negated)
|
||||
return negated;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
const char* name_start = options;
|
||||
const char* name_start = options;
|
||||
|
||||
// Find the end of the name.
|
||||
while (*options && !strchr(", \t\n;=", *options))
|
||||
++options;
|
||||
// Find the end of the name.
|
||||
while (*options && !strchr(", \t\n;=", *options))
|
||||
++options;
|
||||
|
||||
std::string name(name_start, options);
|
||||
std::string name(name_start, options);
|
||||
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
|
||||
if (*options != '=')
|
||||
{
|
||||
options_[name] = (negated ? 0 : 1);
|
||||
}
|
||||
else if (negated)
|
||||
{
|
||||
return negated;
|
||||
}
|
||||
else
|
||||
{
|
||||
++options;
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
if (!*options)
|
||||
return name_start;
|
||||
if (*options != '=')
|
||||
{
|
||||
options_[name] = (negated ? 0 : 1);
|
||||
}
|
||||
else if (negated)
|
||||
{
|
||||
return negated;
|
||||
}
|
||||
else
|
||||
{
|
||||
++options;
|
||||
// Skip spaces.
|
||||
while (*options && strchr(" \t\n", *options))
|
||||
++options;
|
||||
if (!*options)
|
||||
return name_start;
|
||||
|
||||
if (*options == '\'' || *options == '"')
|
||||
{
|
||||
auto sep = *options;
|
||||
auto start = options + 1;
|
||||
do
|
||||
++options;
|
||||
while (*options && *options != sep);
|
||||
if (*options != sep)
|
||||
return start - 1;
|
||||
std::string val(start, options);
|
||||
options_str_[name] = val;
|
||||
if (*options)
|
||||
++options;
|
||||
}
|
||||
else
|
||||
{
|
||||
char* val_end;
|
||||
int val = strtol(options, &val_end, 10);
|
||||
if (val_end == options)
|
||||
return name_start;
|
||||
if (*options == '\'' || *options == '"')
|
||||
{
|
||||
auto sep = *options;
|
||||
auto start = options + 1;
|
||||
do
|
||||
++options;
|
||||
while (*options && *options != sep);
|
||||
if (*options != sep)
|
||||
return start - 1;
|
||||
std::string val(start, options);
|
||||
options_str_[name] = val;
|
||||
if (*options)
|
||||
++options;
|
||||
}
|
||||
else
|
||||
{
|
||||
char* val_end;
|
||||
int val = strtol(options, &val_end, 10);
|
||||
if (val_end == options)
|
||||
return name_start;
|
||||
|
||||
if (*val_end == 'K')
|
||||
{
|
||||
val *= 1024;
|
||||
++val_end;
|
||||
}
|
||||
else if (*val_end == 'M')
|
||||
{
|
||||
val *= 1024 * 1024;
|
||||
++val_end;
|
||||
}
|
||||
else if (*val_end && !strchr(" \t\n,;", *val_end))
|
||||
{
|
||||
return options;
|
||||
}
|
||||
options = val_end;
|
||||
options_[name] = val;
|
||||
}
|
||||
}
|
||||
if (*val_end == 'K')
|
||||
{
|
||||
val *= 1024;
|
||||
++val_end;
|
||||
}
|
||||
else if (*val_end == 'M')
|
||||
{
|
||||
val *= 1024 * 1024;
|
||||
++val_end;
|
||||
}
|
||||
else if (*val_end && !strchr(" \t\n,;", *val_end))
|
||||
{
|
||||
return options;
|
||||
}
|
||||
options = val_end;
|
||||
options_[name] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ namespace spot
|
|||
/// \return The previous value associated to \a option if declared,
|
||||
/// or \a def otherwise.
|
||||
std::string set_str(const char* option,
|
||||
std::string val, std::string def = {});
|
||||
std::string val, std::string def = {});
|
||||
|
||||
/// Acquire all the settings of \a o.
|
||||
void set(const option_map& o);
|
||||
|
|
|
|||
|
|
@ -96,8 +96,8 @@ namespace spot
|
|||
|
||||
if (has_next)
|
||||
{
|
||||
has_next = false;
|
||||
return next;
|
||||
has_next = false;
|
||||
return next;
|
||||
}
|
||||
|
||||
double x;
|
||||
|
|
@ -105,9 +105,9 @@ namespace spot
|
|||
double r;
|
||||
do
|
||||
{
|
||||
x = 2.0 * drand() - 1.0;
|
||||
y = 2.0 * drand() - 1.0;
|
||||
r = x * x + y * y;
|
||||
x = 2.0 * drand() - 1.0;
|
||||
y = 2.0 * drand() - 1.0;
|
||||
r = x * x + y * y;
|
||||
}
|
||||
while (r >= 1.0 || r == 0.0);
|
||||
r = sqrt(-2 * log(r) / r);
|
||||
|
|
@ -124,8 +124,8 @@ namespace spot
|
|||
|
||||
while (s < p)
|
||||
{
|
||||
s -= log(1.0 - drand());
|
||||
++x;
|
||||
s -= log(1.0 - drand());
|
||||
++x;
|
||||
}
|
||||
return x - 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,12 +97,12 @@ namespace spot
|
|||
rand() const
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
int x = round(gen() * s_ + m_);
|
||||
if (x < 0)
|
||||
continue;
|
||||
{
|
||||
int x = round(gen() * s_ + m_);
|
||||
if (x < 0)
|
||||
continue;
|
||||
if (x <= n_)
|
||||
return x;
|
||||
return x;
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
return 0;
|
||||
|
|
@ -128,11 +128,11 @@ namespace spot
|
|||
auto d = std::distance(first, last);
|
||||
if (d > 1)
|
||||
{
|
||||
for (--last; first < last; ++first, --d)
|
||||
{
|
||||
auto i = mrand(d);
|
||||
std::swap(*first, *(first + i));
|
||||
}
|
||||
for (--last; first < last; ++first, --d)
|
||||
{
|
||||
auto i = mrand(d);
|
||||
std::swap(*first, *(first + i));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// @}
|
||||
|
|
|
|||
|
|
@ -37,48 +37,48 @@ namespace spot
|
|||
|
||||
satsolver_command()
|
||||
{
|
||||
satsolver = getenv("SPOT_SATSOLVER");
|
||||
if (!satsolver)
|
||||
{
|
||||
satsolver = "glucose -verb=0 -model %I >%O";
|
||||
return;
|
||||
}
|
||||
prime(satsolver);
|
||||
if (!has('I'))
|
||||
throw std::runtime_error("SPOT_SATSOLVER should contain %I to "
|
||||
"indicate how to use the input filename.");
|
||||
if (!has('O'))
|
||||
throw std::runtime_error("SPOT_SATSOLVER should contain %O to "
|
||||
"indicate how to use the output filename.");
|
||||
satsolver = getenv("SPOT_SATSOLVER");
|
||||
if (!satsolver)
|
||||
{
|
||||
satsolver = "glucose -verb=0 -model %I >%O";
|
||||
return;
|
||||
}
|
||||
prime(satsolver);
|
||||
if (!has('I'))
|
||||
throw std::runtime_error("SPOT_SATSOLVER should contain %I to "
|
||||
"indicate how to use the input filename.");
|
||||
if (!has('O'))
|
||||
throw std::runtime_error("SPOT_SATSOLVER should contain %O to "
|
||||
"indicate how to use the output filename.");
|
||||
}
|
||||
|
||||
int
|
||||
run(printable* in, printable* out)
|
||||
{
|
||||
declare('I', in);
|
||||
declare('O', out);
|
||||
std::ostringstream s;
|
||||
format(s, satsolver);
|
||||
int res = system(s.str().c_str());
|
||||
if (res < 0 || (WIFEXITED(res) && WEXITSTATUS(res) == 127))
|
||||
{
|
||||
s << ": failed to execute";
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
// For POSIX shells, "The exit status of a command that
|
||||
// terminated because it received a signal shall be reported
|
||||
// as greater than 128."
|
||||
if (WIFEXITED(res) && WEXITSTATUS(res) >= 128)
|
||||
{
|
||||
s << ": terminated by signal";
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
if (WIFSIGNALED(res))
|
||||
{
|
||||
s << ": terminated by signal " << WTERMSIG(res);
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
return res;
|
||||
declare('I', in);
|
||||
declare('O', out);
|
||||
std::ostringstream s;
|
||||
format(s, satsolver);
|
||||
int res = system(s.str().c_str());
|
||||
if (res < 0 || (WIFEXITED(res) && WEXITSTATUS(res) == 127))
|
||||
{
|
||||
s << ": failed to execute";
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
// For POSIX shells, "The exit status of a command that
|
||||
// terminated because it received a signal shall be reported
|
||||
// as greater than 128."
|
||||
if (WIFEXITED(res) && WEXITSTATUS(res) >= 128)
|
||||
{
|
||||
s << ": terminated by signal";
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
if (WIFSIGNALED(res))
|
||||
{
|
||||
s << ": terminated by signal " << WTERMSIG(res);
|
||||
throw std::runtime_error(s.str());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -96,25 +96,25 @@ namespace spot
|
|||
int c;
|
||||
while ((c = in->get()) != EOF)
|
||||
{
|
||||
// If a line does not start with 'v ', ignore it.
|
||||
if (c != 'v' || in->get() != ' ')
|
||||
{
|
||||
in->ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
continue;
|
||||
}
|
||||
// Otherwise, read integers one by one.
|
||||
int i;
|
||||
while (*in >> i)
|
||||
{
|
||||
if (i == 0)
|
||||
goto done;
|
||||
sol.push_back(i);
|
||||
}
|
||||
if (!in->eof())
|
||||
// If we haven't reached end-of-file, then we just attempted
|
||||
// to extract something that wasn't an integer. Clear the
|
||||
// fail bit so that will loop over.
|
||||
in->clear();
|
||||
// If a line does not start with 'v ', ignore it.
|
||||
if (c != 'v' || in->get() != ' ')
|
||||
{
|
||||
in->ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
continue;
|
||||
}
|
||||
// Otherwise, read integers one by one.
|
||||
int i;
|
||||
while (*in >> i)
|
||||
{
|
||||
if (i == 0)
|
||||
goto done;
|
||||
sol.push_back(i);
|
||||
}
|
||||
if (!in->eof())
|
||||
// If we haven't reached end-of-file, then we just attempted
|
||||
// to extract something that wasn't an integer. Clear the
|
||||
// fail bit so that will loop over.
|
||||
in->clear();
|
||||
}
|
||||
done:
|
||||
if (in != &std::cin)
|
||||
|
|
@ -149,7 +149,7 @@ namespace spot
|
|||
satsolver::solution_pair
|
||||
satsolver::get_solution()
|
||||
{
|
||||
delete cnf_stream_; // Close the file.
|
||||
delete cnf_stream_; // Close the file.
|
||||
cnf_stream_ = nullptr;
|
||||
|
||||
temporary_file* output = create_tmpfile("sat-", ".out");
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace spot
|
|||
void check() const
|
||||
{
|
||||
if (count_ < 0)
|
||||
throw std::runtime_error("too many SAT clauses (more than INT_MAX)");
|
||||
throw std::runtime_error("too many SAT clauses (more than INT_MAX)");
|
||||
}
|
||||
|
||||
clause_counter& operator++()
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ namespace spot
|
|||
time_info total;
|
||||
for (tm_type::const_iterator i = tm.begin(); i != tm.end(); ++i)
|
||||
{
|
||||
total.utime += i->second.first.utime();
|
||||
total.stime += i->second.first.stime();
|
||||
total.utime += i->second.first.utime();
|
||||
total.stime += i->second.first.stime();
|
||||
}
|
||||
clock_t grand_total = total.utime + total.stime;
|
||||
|
||||
|
|
@ -52,30 +52,30 @@ namespace spot
|
|||
<< std::endl;
|
||||
for (tm_type::const_iterator i = tm.begin(); i != tm.end(); ++i)
|
||||
{
|
||||
// truncate long keys
|
||||
std::string name = i->first;
|
||||
if (name.size() > 22)
|
||||
name.erase(22);
|
||||
// truncate long keys
|
||||
std::string name = i->first;
|
||||
if (name.size() > 22)
|
||||
name.erase(22);
|
||||
|
||||
const spot::timer& t = i->second.first;
|
||||
const char* sep = t.is_running() ? "+|" : " |";
|
||||
const spot::timer& t = i->second.first;
|
||||
const char* sep = t.is_running() ? "+|" : " |";
|
||||
|
||||
os << std::setw(22) << name << sep
|
||||
<< std::setw(6) << t.utime() << ' '
|
||||
<< std::setw(8) << (total.utime ?
|
||||
100.0 * t.utime() / total.utime : 0.)
|
||||
<< sep
|
||||
<< std::setw(6) << t.stime() << ' '
|
||||
<< std::setw(8) << (total.stime ?
|
||||
100.0 * t.stime() / total.stime : 0.)
|
||||
<< sep
|
||||
<< std::setw(6) << t.utime() + t.stime() << ' '
|
||||
<< std::setw(8) << (grand_total ?
|
||||
(100.0 * (t.utime() + t.stime()) /
|
||||
grand_total) : 0.)
|
||||
<< sep
|
||||
<< std::setw(4) << i->second.second
|
||||
<< std::endl;
|
||||
os << std::setw(22) << name << sep
|
||||
<< std::setw(6) << t.utime() << ' '
|
||||
<< std::setw(8) << (total.utime ?
|
||||
100.0 * t.utime() / total.utime : 0.)
|
||||
<< sep
|
||||
<< std::setw(6) << t.stime() << ' '
|
||||
<< std::setw(8) << (total.stime ?
|
||||
100.0 * t.stime() / total.stime : 0.)
|
||||
<< sep
|
||||
<< std::setw(6) << t.utime() + t.stime() << ' '
|
||||
<< std::setw(8) << (grand_total ?
|
||||
(100.0 * (t.utime() + t.stime()) /
|
||||
grand_total) : 0.)
|
||||
<< sep
|
||||
<< std::setw(4) << i->second.second
|
||||
<< std::endl;
|
||||
}
|
||||
os << std::setw(79) << std::setfill('-') << "" << std::setfill(' ')
|
||||
<< std::endl
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ namespace spot
|
|||
assert(i != tm.end());
|
||||
assert(0 < i->second.second);
|
||||
if (0 == --i->second.second)
|
||||
tm.erase(i);
|
||||
tm.erase(i);
|
||||
}
|
||||
|
||||
/// Return the timer \a name.
|
||||
|
|
|
|||
|
|
@ -35,14 +35,14 @@ namespace spot
|
|||
{
|
||||
const char* res = secure_getenv("SPOT_TMPDIR");
|
||||
if (res)
|
||||
return res;
|
||||
return res;
|
||||
return secure_getenv("TMPDIR");
|
||||
}
|
||||
|
||||
static int
|
||||
create_temporary_file(const char* prefix,
|
||||
const char* suffix,
|
||||
char** name)
|
||||
const char* suffix,
|
||||
char** name)
|
||||
throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
static const char* tmpdir = get_tmpdir();
|
||||
|
|
@ -51,30 +51,30 @@ namespace spot
|
|||
size_t len = strlen(prefix);
|
||||
size_t slen = 0;
|
||||
if (suffix)
|
||||
len += slen = strlen(suffix);
|
||||
len += slen = strlen(suffix);
|
||||
char* x = *name = static_cast<char*>(malloc(tmpdirlen + 1 + len + 6 + 1));
|
||||
if (!x)
|
||||
throw std::bad_alloc();
|
||||
throw std::bad_alloc();
|
||||
if (tmpdir)
|
||||
{
|
||||
x = stpcpy(x, tmpdir);
|
||||
if (x[-1] != '/')
|
||||
*x++ = '/';
|
||||
}
|
||||
{
|
||||
x = stpcpy(x, tmpdir);
|
||||
if (x[-1] != '/')
|
||||
*x++ = '/';
|
||||
}
|
||||
x = stpcpy(x, prefix);
|
||||
x = stpcpy(x, "XXXXXX");
|
||||
int fd;
|
||||
if (suffix)
|
||||
{
|
||||
stpcpy(x, suffix);
|
||||
fd = mkstemps(*name, slen);
|
||||
}
|
||||
{
|
||||
stpcpy(x, suffix);
|
||||
fd = mkstemps(*name, slen);
|
||||
}
|
||||
else
|
||||
{
|
||||
fd = mkstemp(*name);
|
||||
}
|
||||
{
|
||||
fd = mkstemp(*name);
|
||||
}
|
||||
if (fd < 0)
|
||||
throw std::runtime_error(std::string("failed to create ") + *name);
|
||||
throw std::runtime_error(std::string("failed to create ") + *name);
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,8 +113,8 @@ namespace spot
|
|||
constexpr trival operator!() const
|
||||
{
|
||||
return trival((val_ == yes_value) ? no_value :
|
||||
(val_ == no_value) ? yes_value :
|
||||
maybe_value);
|
||||
(val_ == no_value) ? yes_value :
|
||||
maybe_value);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -171,8 +171,8 @@ namespace spot
|
|||
inline std::ostream& operator<<(std::ostream& os, trival v)
|
||||
{
|
||||
return os << ((v.val() == trival::no_value) ? "no"
|
||||
: (v.val() == trival::maybe_value) ? "maybe"
|
||||
: "yes");
|
||||
: (v.val() == trival::maybe_value) ? "maybe"
|
||||
: "yes");
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ namespace spot
|
|||
spot::parse_aut_error_list::iterator it;
|
||||
for (auto& err : errors)
|
||||
{
|
||||
if (!filename.empty() && filename != "-")
|
||||
os << filename << ':';
|
||||
os << err.first << ": ";
|
||||
os << err.second << std::endl;
|
||||
printed = true;
|
||||
if (!filename.empty() && filename != "-")
|
||||
os << filename << ':';
|
||||
os << err.first << ": ";
|
||||
os << err.second << std::endl;
|
||||
printed = true;
|
||||
}
|
||||
return printed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
# define YY_DECL \
|
||||
int hoayylex(hoayy::parser::semantic_type *yylval, \
|
||||
spot::location *yylloc, \
|
||||
spot::parse_aut_error_list& error_list)
|
||||
spot::location *yylloc, \
|
||||
spot::parse_aut_error_list& error_list)
|
||||
YY_DECL;
|
||||
|
||||
namespace spot
|
||||
|
|
|
|||
|
|
@ -91,11 +91,11 @@ namespace spot
|
|||
|
||||
struct automaton_parser_options final
|
||||
{
|
||||
bool ignore_abort = false; ///< Skip aborted automata
|
||||
bool debug = false; ///< Run the parser in debug mode?
|
||||
bool trust_hoa = true; ///< Trust properties in HOA files
|
||||
bool raise_errors = false; ///< Raise errors as exceptions.
|
||||
bool want_kripke = false; ///< Parse as a Kripke structure.
|
||||
bool ignore_abort = false; ///< Skip aborted automata
|
||||
bool debug = false; ///< Run the parser in debug mode?
|
||||
bool trust_hoa = true; ///< Trust properties in HOA files
|
||||
bool raise_errors = false; ///< Raise errors as exceptions.
|
||||
bool want_kripke = false; ///< Parse as a Kripke structure.
|
||||
};
|
||||
|
||||
/// \brief Parse a stream of automata
|
||||
|
|
@ -128,7 +128,7 @@ namespace spot
|
|||
/// \param filename The file to read from.
|
||||
/// \param opts Parser options.
|
||||
automaton_stream_parser(const std::string& filename,
|
||||
automaton_parser_options opts = {});
|
||||
automaton_parser_options opts = {});
|
||||
|
||||
/// \brief Parse from an already opened file descriptor.
|
||||
///
|
||||
|
|
@ -136,7 +136,7 @@ namespace spot
|
|||
/// \param filename What to display in error messages.
|
||||
/// \param opts Parser options.
|
||||
automaton_stream_parser(int fd, const std::string& filename,
|
||||
automaton_parser_options opts = {});
|
||||
automaton_parser_options opts = {});
|
||||
|
||||
/// \brief Parse from a buffer
|
||||
///
|
||||
|
|
@ -144,8 +144,8 @@ namespace spot
|
|||
/// \param filename What to display in error messages.
|
||||
/// \param opts Parser options.
|
||||
automaton_stream_parser(const char* data,
|
||||
const std::string& filename,
|
||||
automaton_parser_options opts = {});
|
||||
const std::string& filename,
|
||||
automaton_parser_options opts = {});
|
||||
|
||||
~automaton_stream_parser();
|
||||
|
||||
|
|
@ -165,8 +165,8 @@ namespace spot
|
|||
///
|
||||
/// \warning This function is not reentrant.
|
||||
parsed_aut_ptr parse(const bdd_dict_ptr& dict,
|
||||
environment& env =
|
||||
default_environment::instance());
|
||||
environment& env =
|
||||
default_environment::instance());
|
||||
};
|
||||
|
||||
/// \brief Read the first spot::twa_graph from a file.
|
||||
|
|
@ -187,8 +187,8 @@ namespace spot
|
|||
/// \warning This function is not reentrant.
|
||||
SPOT_API parsed_aut_ptr
|
||||
parse_aut(const std::string& filename,
|
||||
const bdd_dict_ptr& dict,
|
||||
environment& env = default_environment::instance(),
|
||||
automaton_parser_options opts = {});
|
||||
const bdd_dict_ptr& dict,
|
||||
environment& env = default_environment::instance(),
|
||||
automaton_parser_options opts = {});
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace spot
|
|||
{
|
||||
void
|
||||
fix_utf8_locations(const std::string& ltl_string,
|
||||
parse_error_list& error_list)
|
||||
parse_error_list& error_list)
|
||||
{
|
||||
// LUT to convert byte positions to utf8 positions.
|
||||
// (The +2 is to account for position 0, not used,
|
||||
|
|
@ -42,15 +42,15 @@ namespace spot
|
|||
std::string::const_iterator i = b;
|
||||
std::string::const_iterator e = ltl_string.end();
|
||||
|
||||
unsigned n = 0; // number of current utf8 character
|
||||
unsigned prev = 0; // last byte of previous utf8 character
|
||||
unsigned n = 0; // number of current utf8 character
|
||||
unsigned prev = 0; // last byte of previous utf8 character
|
||||
while (i != e)
|
||||
{
|
||||
utf8::next(i, e);
|
||||
++n;
|
||||
unsigned d = std::distance(b, i);
|
||||
while (prev < d)
|
||||
b2u[++prev] = n;
|
||||
utf8::next(i, e);
|
||||
++n;
|
||||
unsigned d = std::distance(b, i);
|
||||
while (prev < d)
|
||||
b2u[++prev] = n;
|
||||
}
|
||||
b2u[++prev] = ++n;
|
||||
|
||||
|
|
@ -58,9 +58,9 @@ namespace spot
|
|||
parse_error_list::iterator it;
|
||||
for (it = error_list.begin(); it != error_list.end(); ++it)
|
||||
{
|
||||
location& l = it->first;
|
||||
l.begin.column = b2u[l.begin.column];
|
||||
l.end.column = b2u[l.end.column];
|
||||
location& l = it->first;
|
||||
l.begin.column = b2u[l.begin.column];
|
||||
l.end.column = b2u[l.end.column];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,45 +68,45 @@ namespace spot
|
|||
{
|
||||
static bool
|
||||
format_parse_errors_aux(std::ostream& os,
|
||||
const std::string& ltl_string,
|
||||
const parse_error_list& error_list,
|
||||
unsigned shift)
|
||||
const std::string& ltl_string,
|
||||
const parse_error_list& error_list,
|
||||
unsigned shift)
|
||||
{
|
||||
bool printed = false;
|
||||
for (auto it: error_list)
|
||||
{
|
||||
os << ">>> " << ltl_string << '\n';
|
||||
const location& l = it.first;
|
||||
{
|
||||
os << ">>> " << ltl_string << '\n';
|
||||
const location& l = it.first;
|
||||
|
||||
unsigned n = 1;
|
||||
for (; n < 4 + l.begin.column + shift; ++n)
|
||||
os << ' ';
|
||||
// Write at least one '^', even if begin==end.
|
||||
os << '^';
|
||||
++n;
|
||||
for (; n < 4 + l.end.column + shift; ++n)
|
||||
os << '^';
|
||||
os << '\n' << it.second << "\n\n";
|
||||
printed = true;
|
||||
}
|
||||
unsigned n = 1;
|
||||
for (; n < 4 + l.begin.column + shift; ++n)
|
||||
os << ' ';
|
||||
// Write at least one '^', even if begin==end.
|
||||
os << '^';
|
||||
++n;
|
||||
for (; n < 4 + l.end.column + shift; ++n)
|
||||
os << '^';
|
||||
os << '\n' << it.second << "\n\n";
|
||||
printed = true;
|
||||
}
|
||||
return printed;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
parsed_formula::format_errors(std::ostream& os,
|
||||
const std::string& real_input,
|
||||
unsigned shift)
|
||||
const std::string& real_input,
|
||||
unsigned shift)
|
||||
{
|
||||
if (utf8::is_valid(input.begin(), input.end()))
|
||||
{
|
||||
parse_error_list fixed = errors;
|
||||
fix_utf8_locations(input, fixed);
|
||||
return format_parse_errors_aux(os, real_input, fixed, shift);
|
||||
parse_error_list fixed = errors;
|
||||
fix_utf8_locations(input, fixed);
|
||||
return format_parse_errors_aux(os, real_input, fixed, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
return format_parse_errors_aux(os, real_input, errors, shift);
|
||||
return format_parse_errors_aux(os, real_input, errors, shift);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@
|
|||
|
||||
# define YY_DECL \
|
||||
int tlyylex (tlyy::parser::semantic_type *yylval, \
|
||||
spot::location *yylloc, \
|
||||
spot::parse_error_list& error_list)
|
||||
spot::location *yylloc, \
|
||||
spot::parse_error_list& error_list)
|
||||
YY_DECL;
|
||||
|
||||
void flex_set_buffer(const std::string& buf, int start_tok, bool lenient);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ namespace spot
|
|||
{
|
||||
auto i = map_.find(name);
|
||||
if (i != map_.end())
|
||||
return true;
|
||||
return true;
|
||||
auto v = aut_->acc().add_set();
|
||||
map_[name] = v;
|
||||
return true;
|
||||
|
|
@ -63,7 +63,7 @@ namespace spot
|
|||
{
|
||||
auto p = map_.find(name);
|
||||
if (p == map_.end())
|
||||
return std::make_pair(false, 0U);
|
||||
return std::make_pair(false, 0U);
|
||||
return std::make_pair(true, acc_cond::mark_t({p->second}));
|
||||
}
|
||||
};
|
||||
|
|
@ -83,9 +83,9 @@ namespace spot
|
|||
std::pair<bool, acc_cond::mark_t> lookup(unsigned n)
|
||||
{
|
||||
if (n < aut_->acc().num_sets())
|
||||
return std::make_pair(true, acc_cond::mark_t({n}));
|
||||
return std::make_pair(true, acc_cond::mark_t({n}));
|
||||
else
|
||||
return std::make_pair(false, 0U);
|
||||
return std::make_pair(false, 0U);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -106,13 +106,13 @@ namespace spot
|
|||
{
|
||||
auto p = map_.find(n);
|
||||
if (p != map_.end())
|
||||
return std::make_pair(true, p->second);
|
||||
return std::make_pair(true, p->second);
|
||||
if (used_ < aut_->acc().num_sets())
|
||||
{
|
||||
auto res = acc_cond::mark_t({used_++});
|
||||
map_[n] = res;
|
||||
return std::make_pair(true, res);
|
||||
}
|
||||
{
|
||||
auto res = acc_cond::mark_t({used_++});
|
||||
map_[n] = res;
|
||||
return std::make_pair(true, res);
|
||||
}
|
||||
return std::make_pair(false, 0U);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -67,15 +67,15 @@ namespace spot
|
|||
// externally), use the new variables.
|
||||
if (lvarnum < varnum)
|
||||
{
|
||||
more -= varnum - lvarnum;
|
||||
lvarnum = varnum;
|
||||
more -= varnum - lvarnum;
|
||||
lvarnum = varnum;
|
||||
}
|
||||
// If we still need more variable, do allocate them.
|
||||
if (more > 0)
|
||||
{
|
||||
bdd_extvarnum(more);
|
||||
varnum += more;
|
||||
lvarnum = varnum;
|
||||
bdd_extvarnum(more);
|
||||
varnum += more;
|
||||
lvarnum = varnum;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,19 +98,19 @@ namespace spot
|
|||
// of the variable space, allocate just the difference.
|
||||
if (!fl.empty() && fl.back().first + fl.back().second == lvarnum)
|
||||
{
|
||||
int res = fl.back().first;
|
||||
int endvar = fl.back().second;
|
||||
assert(n > endvar);
|
||||
extvarnum(n - endvar);
|
||||
fl.pop_back();
|
||||
return res;
|
||||
int res = fl.back().first;
|
||||
int endvar = fl.back().second;
|
||||
assert(n > endvar);
|
||||
extvarnum(n - endvar);
|
||||
fl.pop_back();
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, allocate as much variables as we need.
|
||||
int res = lvarnum;
|
||||
extvarnum(n);
|
||||
return res;
|
||||
// Otherwise, allocate as much variables as we need.
|
||||
int res = lvarnum;
|
||||
extvarnum(n);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,24 +41,24 @@ namespace spot
|
|||
free_list_type::iterator cur;
|
||||
for (cur = fl.begin(); cur != fl.end(); ++cur)
|
||||
{
|
||||
if (cur->second < n)
|
||||
continue;
|
||||
if (n == cur->second)
|
||||
{
|
||||
best = cur;
|
||||
break;
|
||||
}
|
||||
if (best == fl.end()
|
||||
|| cur->second < best->second)
|
||||
best = cur;
|
||||
if (cur->second < n)
|
||||
continue;
|
||||
if (n == cur->second)
|
||||
{
|
||||
best = cur;
|
||||
break;
|
||||
}
|
||||
if (best == fl.end()
|
||||
|| cur->second < best->second)
|
||||
best = cur;
|
||||
}
|
||||
|
||||
// We have found enough free variables.
|
||||
if (best != fl.end())
|
||||
{
|
||||
int result = best->first;
|
||||
remove(best, result, n);
|
||||
return result;
|
||||
int result = best->first;
|
||||
remove(best, result, n);
|
||||
return result;
|
||||
}
|
||||
|
||||
// We haven't found enough adjacent free variables;
|
||||
|
|
@ -73,67 +73,67 @@ namespace spot
|
|||
int end = base + n;
|
||||
for (cur = fl.begin(); cur != fl.end(); ++cur)
|
||||
{
|
||||
int cend = cur->first + cur->second;
|
||||
// cur [...]
|
||||
// to insert [...]
|
||||
// -----------------------
|
||||
// result [...] [...]
|
||||
// (Insert a new range, unconnected.)
|
||||
if (cur->first > end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// cur [...]
|
||||
// to insert [...]
|
||||
// -----------------------
|
||||
// result unknown : we should look at the rest of the freelist.
|
||||
else if (base > cend)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// cur [....[ [......[
|
||||
// to insert [....[ [..[
|
||||
// ----------------------------------
|
||||
// result [......[ [......[
|
||||
else if (cur->first <= base)
|
||||
{
|
||||
if (cend >= end)
|
||||
// second case : nothing to do
|
||||
return;
|
||||
// cur->second is set below.
|
||||
}
|
||||
// cur [....[ [..[
|
||||
// to insert [....[ [.......[
|
||||
// ----------------------------------
|
||||
// result [......[ [.......[
|
||||
else
|
||||
{
|
||||
cur->first = base;
|
||||
// cur->second is set below.
|
||||
}
|
||||
int cend = cur->first + cur->second;
|
||||
// cur [...]
|
||||
// to insert [...]
|
||||
// -----------------------
|
||||
// result [...] [...]
|
||||
// (Insert a new range, unconnected.)
|
||||
if (cur->first > end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// cur [...]
|
||||
// to insert [...]
|
||||
// -----------------------
|
||||
// result unknown : we should look at the rest of the freelist.
|
||||
else if (base > cend)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// cur [....[ [......[
|
||||
// to insert [....[ [..[
|
||||
// ----------------------------------
|
||||
// result [......[ [......[
|
||||
else if (cur->first <= base)
|
||||
{
|
||||
if (cend >= end)
|
||||
// second case : nothing to do
|
||||
return;
|
||||
// cur->second is set below.
|
||||
}
|
||||
// cur [....[ [..[
|
||||
// to insert [....[ [.......[
|
||||
// ----------------------------------
|
||||
// result [......[ [.......[
|
||||
else
|
||||
{
|
||||
cur->first = base;
|
||||
// cur->second is set below.
|
||||
}
|
||||
|
||||
// We get here in one of these three situations:
|
||||
//
|
||||
// cur [....[ [....[ [..[
|
||||
// to insert [....[ [....[ [.......[
|
||||
// -------------------------------------------
|
||||
// result [......[ [......[ [.......[
|
||||
//
|
||||
// cur->first is already set, be cur->second has yet to be.
|
||||
end = std::max(cend, end);
|
||||
cur->second = end - cur->first;
|
||||
// Since we have extended the current range, maybe the next
|
||||
// items on the list should be merged.
|
||||
free_list_type::iterator next = cur;
|
||||
++next;
|
||||
while (next != fl.end() && next->first <= end)
|
||||
{
|
||||
end = std::max(next->first + next->second, end);
|
||||
cur->second = end - cur->first;
|
||||
free_list_type::iterator next2 = next++;
|
||||
fl.erase(next2);
|
||||
}
|
||||
return;
|
||||
// We get here in one of these three situations:
|
||||
//
|
||||
// cur [....[ [....[ [..[
|
||||
// to insert [....[ [....[ [.......[
|
||||
// -------------------------------------------
|
||||
// result [......[ [......[ [.......[
|
||||
//
|
||||
// cur->first is already set, be cur->second has yet to be.
|
||||
end = std::max(cend, end);
|
||||
cur->second = end - cur->first;
|
||||
// Since we have extended the current range, maybe the next
|
||||
// items on the list should be merged.
|
||||
free_list_type::iterator next = cur;
|
||||
++next;
|
||||
while (next != fl.end() && next->first <= end)
|
||||
{
|
||||
end = std::max(next->first + next->second, end);
|
||||
cur->second = end - cur->first;
|
||||
free_list_type::iterator next2 = next++;
|
||||
fl.erase(next2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// We reach this place either because a new unconnected range
|
||||
|
|
@ -148,15 +148,15 @@ namespace spot
|
|||
int end = base + n;
|
||||
while (cur != fl.end() && cur->first < end)
|
||||
{
|
||||
int cend = cur->first + cur->second;
|
||||
// Remove may invalidate the current iterator, so advance it first.
|
||||
free_list_type::iterator old = cur++;
|
||||
if (cend >= base)
|
||||
{
|
||||
int newbase = std::max(base, old->first);
|
||||
int q = std::min(cend, end) - newbase;
|
||||
remove(old, newbase, q);
|
||||
}
|
||||
int cend = cur->first + cur->second;
|
||||
// Remove may invalidate the current iterator, so advance it first.
|
||||
free_list_type::iterator old = cur++;
|
||||
if (cend >= base)
|
||||
{
|
||||
int newbase = std::max(base, old->first);
|
||||
int q = std::min(cend, end) - newbase;
|
||||
remove(old, newbase, q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -165,31 +165,31 @@ namespace spot
|
|||
{
|
||||
if (base == i->first)
|
||||
{
|
||||
// Removing at the beginning of the range
|
||||
i->second -= n;
|
||||
assert(i->second >= 0);
|
||||
// Erase the range if it's now empty.
|
||||
if (i->second == 0)
|
||||
fl.erase(i);
|
||||
else
|
||||
i->first += n;
|
||||
// Removing at the beginning of the range
|
||||
i->second -= n;
|
||||
assert(i->second >= 0);
|
||||
// Erase the range if it's now empty.
|
||||
if (i->second == 0)
|
||||
fl.erase(i);
|
||||
else
|
||||
i->first += n;
|
||||
}
|
||||
else if (base + n == i->first + i->second)
|
||||
{
|
||||
// Removing at the end of the range
|
||||
i->second -= n;
|
||||
assert(i->second > 0); // cannot be empty because base != i->first
|
||||
// Removing at the end of the range
|
||||
i->second -= n;
|
||||
assert(i->second > 0); // cannot be empty because base != i->first
|
||||
}
|
||||
else
|
||||
{
|
||||
// Removing in the middle of a range.
|
||||
int b1 = i->first;
|
||||
int n1 = base - i->first;
|
||||
int n2 = i->first + i->second - base - n;
|
||||
assert(n1 > 0);
|
||||
assert(n2 > 0);
|
||||
*i = pos_lenght_pair(base + n, n2);
|
||||
fl.insert(i, pos_lenght_pair(b1, n1));
|
||||
// Removing in the middle of a range.
|
||||
int b1 = i->first;
|
||||
int n1 = base - i->first;
|
||||
int n2 = i->first + i->second - base - n;
|
||||
assert(n1 > 0);
|
||||
assert(n2 > 0);
|
||||
*i = pos_lenght_pair(base + n, n2);
|
||||
fl.insert(i, pos_lenght_pair(b1, n1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ namespace spot
|
|||
trim(std::string& str)
|
||||
{
|
||||
str.erase(std::find_if(str.rbegin(), str.rend(),
|
||||
std::not1(std::ptr_fun<int, int>
|
||||
(std::isspace))).base(),
|
||||
str.end());
|
||||
std::not1(std::ptr_fun<int, int>
|
||||
(std::isspace))).base(),
|
||||
str.end());
|
||||
str.erase(str.begin(),
|
||||
std::find_if(str.begin(), str.end(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))));
|
||||
std::find_if(str.begin(), str.end(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace spot
|
|||
{
|
||||
for (auto s: a.sets())
|
||||
if (m[s] > 0)
|
||||
--m[s];
|
||||
--m[s];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ namespace spot
|
|||
std::vector<unsigned> res;
|
||||
for (unsigned n = 0; n < max; ++n)
|
||||
if (m[n] > w.m[n])
|
||||
res.push_back(n);
|
||||
res.push_back(n);
|
||||
return acc_cond::mark_t(res.begin(), res.end());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace spot
|
|||
/// the corresponding counter in w.
|
||||
acc_cond::mark_t diff(const acc_cond& acc, const weight& w) const;
|
||||
friend std::ostream& operator<<(std::ostream& os,
|
||||
const weight& w);
|
||||
const weight& w);
|
||||
|
||||
private:
|
||||
std::vector<int> m;
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ namespace spot
|
|||
bool is_stuttering_transition = (get_tgba_condition()
|
||||
== (dest)->get_tgba_condition());
|
||||
bool dest_is_livelock_accepting =
|
||||
dest->is_livelock_accepting_state();
|
||||
dest->is_livelock_accepting_state();
|
||||
|
||||
//Before deleting stuttering transitions, propaged back livelock
|
||||
//and initial state's properties
|
||||
|
|
@ -319,7 +319,7 @@ namespace spot
|
|||
// they are not cloned.
|
||||
if (trans)
|
||||
for (auto& t: *trans)
|
||||
delete t;
|
||||
delete t;
|
||||
delete trans;
|
||||
|
||||
std::unordered_map<int, transitions*, std::hash<int> >::iterator i =
|
||||
|
|
@ -338,8 +338,8 @@ namespace spot
|
|||
|
||||
|
||||
ta_explicit::ta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state):
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state):
|
||||
ta(tgba->get_dict()),
|
||||
tgba_(tgba),
|
||||
artificial_initial_state_(artificial_initial_state)
|
||||
|
|
@ -351,7 +351,7 @@ namespace spot
|
|||
{
|
||||
auto is = add_state(artificial_initial_state);
|
||||
assert(is == artificial_initial_state);
|
||||
(void)is;
|
||||
(void)is;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -361,8 +361,8 @@ namespace spot
|
|||
for (it = states_set_.begin(); it != states_set_.end(); ++it)
|
||||
{
|
||||
auto* s = const_cast<state_ta_explicit*>
|
||||
(down_cast<const state_ta_explicit*>(*it));
|
||||
assert(s);
|
||||
(down_cast<const state_ta_explicit*>(*it));
|
||||
assert(s);
|
||||
s->free_transitions();
|
||||
s->get_tgba_state()->destroy();
|
||||
delete s;
|
||||
|
|
@ -390,11 +390,11 @@ namespace spot
|
|||
auto add_state = initial_states_set_.insert(s);
|
||||
if (get_artificial_initial_state())
|
||||
if (add_state.second)
|
||||
{
|
||||
auto i =
|
||||
down_cast<state_ta_explicit*>(get_artificial_initial_state());
|
||||
create_transition(i, condition, 0U, s);
|
||||
}
|
||||
{
|
||||
auto i =
|
||||
down_cast<state_ta_explicit*>(get_artificial_initial_state());
|
||||
create_transition(i, condition, 0U, s);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -411,9 +411,9 @@ namespace spot
|
|||
|
||||
void
|
||||
ta_explicit::create_transition(state_ta_explicit* source, bdd condition,
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
const state_ta_explicit* dest,
|
||||
bool add_at_beginning)
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
const state_ta_explicit* dest,
|
||||
bool add_at_beginning)
|
||||
{
|
||||
state_ta_explicit::transition* t = new state_ta_explicit::transition;
|
||||
t->dest = dest;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
ta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr);
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr);
|
||||
|
||||
const_twa_ptr
|
||||
get_tgba() const;
|
||||
|
|
@ -55,9 +55,9 @@ namespace spot
|
|||
|
||||
void
|
||||
create_transition(state_ta_explicit* source, bdd condition,
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
const state_ta_explicit* dest,
|
||||
bool add_at_beginning = false);
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
const state_ta_explicit* dest,
|
||||
bool add_at_beginning = false);
|
||||
|
||||
void
|
||||
delete_stuttering_transitions();
|
||||
|
|
@ -142,10 +142,10 @@ namespace spot
|
|||
typedef std::list<transition*> transitions;
|
||||
|
||||
state_ta_explicit(const state* tgba_state, const bdd tgba_condition,
|
||||
bool is_initial_state = false,
|
||||
bool is_accepting_state = false,
|
||||
bool is_livelock_accepting_state = false,
|
||||
transitions* trans = nullptr) :
|
||||
bool is_initial_state = false,
|
||||
bool is_accepting_state = false,
|
||||
bool is_livelock_accepting_state = false,
|
||||
transitions* trans = nullptr) :
|
||||
tgba_state_(tgba_state), tgba_condition_(tgba_condition),
|
||||
is_initial_state_(is_initial_state), is_accepting_state_(
|
||||
is_accepting_state), is_livelock_accepting_state_(
|
||||
|
|
@ -246,8 +246,8 @@ namespace spot
|
|||
|
||||
inline ta_explicit_ptr
|
||||
make_ta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr)
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr)
|
||||
{
|
||||
return std::make_shared<ta_explicit>(tgba, n_acc, artificial_initial_state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ namespace spot
|
|||
////////////////////////////////////////////////////////////
|
||||
// ta_succ_iterator_product
|
||||
ta_succ_iterator_product::ta_succ_iterator_product(const state_ta_product* s,
|
||||
const ta* t,
|
||||
const kripke* k)
|
||||
const ta* t,
|
||||
const kripke* k)
|
||||
: source_(s), ta_(t), kripke_(k)
|
||||
{
|
||||
kripke_source_condition = kripke_->state_condition(s->get_kripke_state());
|
||||
|
|
@ -243,7 +243,7 @@ namespace spot
|
|||
|
||||
|
||||
ta_product::ta_product(const const_ta_ptr& testing_automata,
|
||||
const const_kripke_ptr& kripke_structure):
|
||||
const const_kripke_ptr& kripke_structure):
|
||||
ta(testing_automata->get_dict()),
|
||||
dict_(testing_automata->get_dict()),
|
||||
ta_(testing_automata),
|
||||
|
|
@ -292,9 +292,9 @@ namespace spot
|
|||
|
||||
for (auto s: ta_init_states_set)
|
||||
if (artificial_initial_state ||
|
||||
(kripke_init_condition == ta_->get_state_condition(s)))
|
||||
initial_states_set.insert(new state_ta_product(s,
|
||||
kripke_init->clone()));
|
||||
(kripke_init_condition == ta_->get_state_condition(s)))
|
||||
initial_states_set.insert(new state_ta_product(s,
|
||||
kripke_init->clone()));
|
||||
|
||||
kripke_init->destroy();
|
||||
return initial_states_set;
|
||||
|
|
@ -316,8 +316,8 @@ namespace spot
|
|||
const state_ta_product* stp = down_cast<const state_ta_product*> (s);
|
||||
assert(s);
|
||||
return new ta_succ_iterator_product_by_changeset(stp,
|
||||
ta_.get(), kripke_.get(),
|
||||
changeset);
|
||||
ta_.get(), kripke_.get(),
|
||||
changeset);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -402,7 +402,7 @@ namespace spot
|
|||
|
||||
ta_succ_iterator_product_by_changeset::
|
||||
ta_succ_iterator_product_by_changeset(const state_ta_product* s, const ta* t,
|
||||
const kripke* k, bdd changeset)
|
||||
const kripke* k, bdd changeset)
|
||||
: ta_succ_iterator_product(s, t, k)
|
||||
{
|
||||
current_condition_ = changeset;
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ namespace spot
|
|||
/// \param testing_automaton The TA component in the product.
|
||||
/// \param kripke_structure The Kripke component in the product.
|
||||
ta_product(const const_ta_ptr& testing_automaton,
|
||||
const const_kripke_ptr& kripke_structure);
|
||||
const const_kripke_ptr& kripke_structure);
|
||||
|
||||
virtual
|
||||
~ta_product();
|
||||
|
|
@ -197,7 +197,7 @@ namespace spot
|
|||
typedef std::shared_ptr<ta_product> 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,
|
||||
const const_kripke_ptr& kripke_structure)
|
||||
const const_kripke_ptr& kripke_structure)
|
||||
{
|
||||
return std::make_shared<ta_product>(testing_automaton, kripke_structure);
|
||||
}
|
||||
|
|
@ -207,8 +207,8 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
ta_succ_iterator_product_by_changeset(const state_ta_product* s,
|
||||
const ta* t, const kripke* k,
|
||||
bdd changeset);
|
||||
const ta* t, const kripke* k,
|
||||
bdd changeset);
|
||||
|
||||
/// \brief Move to the next successor in the Kripke structure
|
||||
void next_kripke_dest();
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ namespace spot
|
|||
{
|
||||
|
||||
tgta_explicit::tgta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state) :
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state) :
|
||||
tgta(tgba->get_dict()),
|
||||
ta_(make_ta_explicit(tgba, n_acc, artificial_initial_state))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
tgta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state);
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state);
|
||||
|
||||
// tgba interface
|
||||
virtual spot::state* get_init_state() const override;
|
||||
|
|
@ -63,9 +63,9 @@ namespace spot
|
|||
|
||||
inline tgta_explicit_ptr
|
||||
make_tgta_explicit(const const_twa_ptr& tgba, unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr)
|
||||
state_ta_explicit* artificial_initial_state = nullptr)
|
||||
{
|
||||
return std::make_shared<tgta_explicit>(tgba, n_acc,
|
||||
artificial_initial_state);
|
||||
artificial_initial_state);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace spot
|
|||
// tgta_product
|
||||
|
||||
tgta_product::tgta_product(const const_kripke_ptr& left,
|
||||
const const_tgta_ptr& right):
|
||||
const const_tgta_ptr& right):
|
||||
twa_product(left, right)
|
||||
{
|
||||
}
|
||||
|
|
@ -207,7 +207,7 @@ namespace spot
|
|||
kripke_current_dest_state->clone(),
|
||||
tgta_succ_it_->dst(), pool_);
|
||||
current_acceptance_conditions_
|
||||
= tgta_succ_it_->acc();
|
||||
= tgta_succ_it_->acc();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
tgta_product(const const_kripke_ptr& left,
|
||||
const const_tgta_ptr& right);
|
||||
const const_tgta_ptr& right);
|
||||
|
||||
virtual const state* get_init_state() const override;
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ namespace spot
|
|||
};
|
||||
|
||||
inline twa_ptr product(const const_kripke_ptr& left,
|
||||
const const_tgta_ptr& right)
|
||||
const const_tgta_ptr& right)
|
||||
{
|
||||
return std::make_shared<tgta_product>(left, right);
|
||||
}
|
||||
|
|
@ -52,9 +52,9 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
tgta_succ_iterator_product(const state_product* s,
|
||||
const const_kripke_ptr& k,
|
||||
const const_tgta_ptr& tgta,
|
||||
fixed_size_pool* pool);
|
||||
const const_kripke_ptr& k,
|
||||
const const_tgta_ptr& tgta,
|
||||
fixed_size_pool* pool);
|
||||
|
||||
virtual
|
||||
~tgta_succ_iterator_product();
|
||||
|
|
|
|||
|
|
@ -35,109 +35,109 @@ namespace spot
|
|||
void
|
||||
parse_opts(const char* options)
|
||||
{
|
||||
const char* orig = options;
|
||||
while (char c = *options++)
|
||||
switch (c)
|
||||
{
|
||||
case '.':
|
||||
{
|
||||
// Copy the value in a string, so future calls to
|
||||
// parse_opts do not fail if the environment has
|
||||
// changed. (This matters particularly in an ipython
|
||||
// notebook, where it is tempting to redefine
|
||||
// SPOT_DOTDEFAULT.)
|
||||
static std::string def = []()
|
||||
{
|
||||
auto s = getenv("SPOT_DOTDEFAULT");
|
||||
return s ? s : "";
|
||||
}();
|
||||
// Prevent infinite recursions...
|
||||
if (orig == def.c_str())
|
||||
throw std::runtime_error
|
||||
(std::string("SPOT_DOTDEFAULT should not contain '.'"));
|
||||
if (!def.empty())
|
||||
parse_opts(def.c_str());
|
||||
break;
|
||||
}
|
||||
case 'A':
|
||||
opt_hide_sets_ = true;
|
||||
break;
|
||||
case 'c':
|
||||
opt_circles_ = true;
|
||||
break;
|
||||
case 'C':
|
||||
if (*options != '(')
|
||||
throw std::runtime_error
|
||||
("invalid node color specification for print_dot()");
|
||||
{
|
||||
auto* end = strchr(++options, ')');
|
||||
if (!end)
|
||||
throw std::runtime_error
|
||||
("invalid node color specification for print_dot()");
|
||||
opt_node_color_ = std::string(options, end - options);
|
||||
options = end + 1;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
opt_horizontal_ = true;
|
||||
break;
|
||||
case 'f':
|
||||
if (*options != '(')
|
||||
throw std::runtime_error
|
||||
(std::string("invalid font specification for dotty()"));
|
||||
{
|
||||
auto* end = strchr(++options, ')');
|
||||
if (!end)
|
||||
throw std::runtime_error
|
||||
(std::string("invalid font specification for dotty()"));
|
||||
opt_font_ = std::string(options, end - options);
|
||||
options = end + 1;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
opt_horizontal_ = false;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'B':
|
||||
case 'e':
|
||||
case 'n':
|
||||
case 'N':
|
||||
case 'o':
|
||||
case 'r':
|
||||
case 'R':
|
||||
case 's':
|
||||
case 't':
|
||||
case '+':
|
||||
case '<':
|
||||
case '#':
|
||||
// All these options are implemented by dotty() on TGBA,
|
||||
// but are not implemented here. We simply ignore them,
|
||||
// because raising an exception if they are in
|
||||
// SPOT_DEFAULT would be annoying.
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error
|
||||
(std::string("unknown option for dotty(): ") + c);
|
||||
}
|
||||
const char* orig = options;
|
||||
while (char c = *options++)
|
||||
switch (c)
|
||||
{
|
||||
case '.':
|
||||
{
|
||||
// Copy the value in a string, so future calls to
|
||||
// parse_opts do not fail if the environment has
|
||||
// changed. (This matters particularly in an ipython
|
||||
// notebook, where it is tempting to redefine
|
||||
// SPOT_DOTDEFAULT.)
|
||||
static std::string def = []()
|
||||
{
|
||||
auto s = getenv("SPOT_DOTDEFAULT");
|
||||
return s ? s : "";
|
||||
}();
|
||||
// Prevent infinite recursions...
|
||||
if (orig == def.c_str())
|
||||
throw std::runtime_error
|
||||
(std::string("SPOT_DOTDEFAULT should not contain '.'"));
|
||||
if (!def.empty())
|
||||
parse_opts(def.c_str());
|
||||
break;
|
||||
}
|
||||
case 'A':
|
||||
opt_hide_sets_ = true;
|
||||
break;
|
||||
case 'c':
|
||||
opt_circles_ = true;
|
||||
break;
|
||||
case 'C':
|
||||
if (*options != '(')
|
||||
throw std::runtime_error
|
||||
("invalid node color specification for print_dot()");
|
||||
{
|
||||
auto* end = strchr(++options, ')');
|
||||
if (!end)
|
||||
throw std::runtime_error
|
||||
("invalid node color specification for print_dot()");
|
||||
opt_node_color_ = std::string(options, end - options);
|
||||
options = end + 1;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
opt_horizontal_ = true;
|
||||
break;
|
||||
case 'f':
|
||||
if (*options != '(')
|
||||
throw std::runtime_error
|
||||
(std::string("invalid font specification for dotty()"));
|
||||
{
|
||||
auto* end = strchr(++options, ')');
|
||||
if (!end)
|
||||
throw std::runtime_error
|
||||
(std::string("invalid font specification for dotty()"));
|
||||
opt_font_ = std::string(options, end - options);
|
||||
options = end + 1;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
opt_horizontal_ = false;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'B':
|
||||
case 'e':
|
||||
case 'n':
|
||||
case 'N':
|
||||
case 'o':
|
||||
case 'r':
|
||||
case 'R':
|
||||
case 's':
|
||||
case 't':
|
||||
case '+':
|
||||
case '<':
|
||||
case '#':
|
||||
// All these options are implemented by dotty() on TGBA,
|
||||
// but are not implemented here. We simply ignore them,
|
||||
// because raising an exception if they are in
|
||||
// SPOT_DEFAULT would be annoying.
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error
|
||||
(std::string("unknown option for dotty(): ") + c);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
dotty_bfs(std::ostream& os, const const_ta_ptr& a,
|
||||
const char* opt) :
|
||||
const char* opt) :
|
||||
ta_reachable_iterator_breadth_first(a), os_(os)
|
||||
{
|
||||
parse_opts(opt ? opt : ".");
|
||||
parse_opts(opt ? opt : ".");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -145,56 +145,56 @@ namespace spot
|
|||
{
|
||||
os_ << "digraph G {\n";
|
||||
|
||||
if (opt_horizontal_)
|
||||
os_ << " rankdir=LR\n";
|
||||
if (opt_circles_)
|
||||
os_ << " node [shape=\"circle\"]\n";
|
||||
if (!opt_node_color_.empty())
|
||||
os_ << " node [style=\"filled\", fillcolor=\""
|
||||
<< opt_node_color_ << "\"]\n";
|
||||
if (!opt_font_.empty())
|
||||
os_ << " fontname=\"" << opt_font_
|
||||
<< "\"\n node [fontname=\"" << opt_font_
|
||||
<< "\"]\n edge [fontname=\"" << opt_font_
|
||||
<< "\"]\n";
|
||||
if (opt_horizontal_)
|
||||
os_ << " rankdir=LR\n";
|
||||
if (opt_circles_)
|
||||
os_ << " node [shape=\"circle\"]\n";
|
||||
if (!opt_node_color_.empty())
|
||||
os_ << " node [style=\"filled\", fillcolor=\""
|
||||
<< opt_node_color_ << "\"]\n";
|
||||
if (!opt_font_.empty())
|
||||
os_ << " fontname=\"" << opt_font_
|
||||
<< "\"\n node [fontname=\"" << opt_font_
|
||||
<< "\"]\n edge [fontname=\"" << opt_font_
|
||||
<< "\"]\n";
|
||||
|
||||
// Always copy the environment variable into a static string,
|
||||
// so that we (1) look it up once, but (2) won't crash if the
|
||||
// environment is changed.
|
||||
static std::string extra = []()
|
||||
{
|
||||
auto s = getenv("SPOT_DOTEXTRA");
|
||||
return s ? s : "";
|
||||
}();
|
||||
// Any extra text passed in the SPOT_DOTEXTRA environment
|
||||
// variable should be output at the end of the "header", so
|
||||
// that our setup can be overridden.
|
||||
if (!extra.empty())
|
||||
os_ << " " << extra << '\n';
|
||||
// Always copy the environment variable into a static string,
|
||||
// so that we (1) look it up once, but (2) won't crash if the
|
||||
// environment is changed.
|
||||
static std::string extra = []()
|
||||
{
|
||||
auto s = getenv("SPOT_DOTEXTRA");
|
||||
return s ? s : "";
|
||||
}();
|
||||
// Any extra text passed in the SPOT_DOTEXTRA environment
|
||||
// variable should be output at the end of the "header", so
|
||||
// that our setup can be overridden.
|
||||
if (!extra.empty())
|
||||
os_ << " " << extra << '\n';
|
||||
|
||||
artificial_initial_state_ = t_automata_->get_artificial_initial_state();
|
||||
|
||||
ta::const_states_set_t init_states_set;
|
||||
|
||||
if (artificial_initial_state_)
|
||||
{
|
||||
init_states_set.insert(artificial_initial_state_);
|
||||
os_ << " 0 [label=\"\", style=invis, height=0]\n 0 -> 1\n";
|
||||
}
|
||||
{
|
||||
init_states_set.insert(artificial_initial_state_);
|
||||
os_ << " 0 [label=\"\", style=invis, height=0]\n 0 -> 1\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = 0;
|
||||
init_states_set = t_automata_->get_initial_states_set();
|
||||
for (auto s: init_states_set)
|
||||
{
|
||||
bdd init_condition = t_automata_->get_state_condition(s);
|
||||
std::string label = bdd_format_formula(t_automata_->get_dict(),
|
||||
init_condition);
|
||||
++n;
|
||||
os_ << " " << -n << " [label=\"\", style=invis, height=0]\n "
|
||||
<< -n << " -> " << n << " [label=\"" << label << "\"]\n";
|
||||
}
|
||||
}
|
||||
{
|
||||
int n = 0;
|
||||
init_states_set = t_automata_->get_initial_states_set();
|
||||
for (auto s: init_states_set)
|
||||
{
|
||||
bdd init_condition = t_automata_->get_state_condition(s);
|
||||
std::string label = bdd_format_formula(t_automata_->get_dict(),
|
||||
init_condition);
|
||||
++n;
|
||||
os_ << " " << -n << " [label=\"\", style=invis, height=0]\n "
|
||||
<< -n << " -> " << n << " [label=\"" << label << "\"]\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -209,41 +209,41 @@ namespace spot
|
|||
|
||||
std::string style;
|
||||
if (t_automata_->is_accepting_state(s))
|
||||
style = ",peripheries=2";
|
||||
style = ",peripheries=2";
|
||||
|
||||
if (t_automata_->is_livelock_accepting_state(s))
|
||||
style += ",shape=box";
|
||||
if (t_automata_->is_livelock_accepting_state(s))
|
||||
style += ",shape=box";
|
||||
|
||||
os_ << " " << n << " [label=";
|
||||
if (s == artificial_initial_state_)
|
||||
os_ << "init";
|
||||
else
|
||||
os_ << quote_unless_bare_word(t_automata_->format_state(s));
|
||||
os_ << style << "]\n";
|
||||
os_ << " " << n << " [label=";
|
||||
if (s == artificial_initial_state_)
|
||||
os_ << "init";
|
||||
else
|
||||
os_ << quote_unless_bare_word(t_automata_->format_state(s));
|
||||
os_ << style << "]\n";
|
||||
}
|
||||
|
||||
void
|
||||
process_link(int in, int out, const ta_succ_iterator* si)
|
||||
{
|
||||
bdd_dict_ptr d = t_automata_->get_dict();
|
||||
std::string label =
|
||||
((in == 1 && artificial_initial_state_)
|
||||
? bdd_format_formula(d, si->cond())
|
||||
: bdd_format_accset(d, si->cond()));
|
||||
bdd_dict_ptr d = t_automata_->get_dict();
|
||||
std::string label =
|
||||
((in == 1 && artificial_initial_state_)
|
||||
? bdd_format_formula(d, si->cond())
|
||||
: bdd_format_accset(d, si->cond()));
|
||||
|
||||
if (label.empty())
|
||||
label = "{}";
|
||||
if (label.empty())
|
||||
label = "{}";
|
||||
|
||||
if (!opt_hide_sets_)
|
||||
{
|
||||
label += "\n";
|
||||
label += t_automata_->acc().
|
||||
format(si->acc());
|
||||
}
|
||||
if (!opt_hide_sets_)
|
||||
{
|
||||
label += "\n";
|
||||
label += t_automata_->acc().
|
||||
format(si->acc());
|
||||
}
|
||||
|
||||
os_ << " " << in << " -> " << out << " [label=\"";
|
||||
escape_str(os_, label);
|
||||
os_ << "\"]\n";
|
||||
escape_str(os_, label);
|
||||
os_ << "\"]\n";
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -26,5 +26,5 @@ namespace spot
|
|||
{
|
||||
SPOT_API std::ostream&
|
||||
print_dot(std::ostream& os, const const_ta_ptr& a,
|
||||
const char* opt = nullptr);
|
||||
const char* opt = nullptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,10 +102,10 @@ namespace spot
|
|||
(ta_init_it_->dst()), kripke_init_state->clone());
|
||||
|
||||
if (!h.emplace(init, num + 1).second)
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
|
||||
scc.push(++num);
|
||||
arc.push(0U);
|
||||
|
|
@ -146,7 +146,7 @@ namespace spot
|
|||
}
|
||||
|
||||
// fill rem with any component removed,
|
||||
auto i = h.find(curr);
|
||||
auto i = h.find(curr);
|
||||
assert(i != h.end());
|
||||
|
||||
scc.rem().push_front(curr);
|
||||
|
|
@ -168,7 +168,7 @@ namespace spot
|
|||
{
|
||||
// removing states
|
||||
for (auto j: scc.rem())
|
||||
h[j] = -1;
|
||||
h[j] = -1;
|
||||
dec_depth(scc.rem().size());
|
||||
scc.pop();
|
||||
assert(!arc.empty());
|
||||
|
|
@ -209,7 +209,7 @@ namespace spot
|
|||
// We do not need SUCC from now on.
|
||||
|
||||
// Are we going to a new state?
|
||||
auto p = h.emplace(dest, num + 1);
|
||||
auto p = h.emplace(dest, num + 1);
|
||||
if (p.second)
|
||||
{
|
||||
// Number it, stack it, and register its successors
|
||||
|
|
@ -277,23 +277,23 @@ namespace spot
|
|||
|
||||
scc.rem().splice(scc.rem().end(), rem);
|
||||
bool is_accepting_sscc = scc.top().is_accepting
|
||||
|| a_->acc().accepting(scc.top().condition);
|
||||
|| a_->acc().accepting(scc.top().condition);
|
||||
|
||||
if (is_accepting_sscc)
|
||||
{
|
||||
trace
|
||||
<< "PASS 1: SUCCESS: a_->is_livelock_accepting_state(curr): "
|
||||
<< a_->is_livelock_accepting_state(curr) << '\n';
|
||||
<< "PASS 1: SUCCESS: a_->is_livelock_accepting_state(curr): "
|
||||
<< a_->is_livelock_accepting_state(curr) << '\n';
|
||||
trace
|
||||
<< "PASS 1: scc.top().condition : "
|
||||
<< scc.top().condition << '\n';
|
||||
<< scc.top().condition << '\n';
|
||||
trace
|
||||
<< "PASS 1: a_->acc().all_sets() : "
|
||||
<< (a_->acc().all_sets()) << '\n';
|
||||
<< (a_->acc().all_sets()) << '\n';
|
||||
trace
|
||||
<< ("PASS 1 CYCLE and accepting? ")
|
||||
<< a_->acc().accepting(scc.top().condition)
|
||||
<< std::endl;
|
||||
<< ("PASS 1 CYCLE and accepting? ")
|
||||
<< a_->acc().accepting(scc.top().condition)
|
||||
<< std::endl;
|
||||
clear(h, todo, ta_init_it_);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -315,19 +315,19 @@ namespace spot
|
|||
h_livelock_root = h[livelock_roots.top()];
|
||||
|
||||
if (heuristic_livelock_detection(dest, h, h_livelock_root,
|
||||
liveset_curr))
|
||||
liveset_curr))
|
||||
{
|
||||
clear(h, todo, ta_init_it_);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const state* succ: liveset_dest)
|
||||
if (heuristic_livelock_detection(succ, h, h_livelock_root,
|
||||
liveset_curr))
|
||||
{
|
||||
clear(h, todo, ta_init_it_);
|
||||
return true;
|
||||
}
|
||||
if (heuristic_livelock_detection(succ, h, h_livelock_root,
|
||||
liveset_curr))
|
||||
{
|
||||
clear(h, todo, ta_init_it_);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -403,11 +403,11 @@ namespace spot
|
|||
auto init = ta_init_it_.front();
|
||||
ta_init_it_.pop();
|
||||
|
||||
if (!h.emplace(init, num + 1).second)
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
if (!h.emplace(init, num + 1).second)
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
|
||||
sscc.push(num);
|
||||
sscc.top().is_accepting = t->is_livelock_accepting_state(init);
|
||||
|
|
@ -435,7 +435,7 @@ namespace spot
|
|||
trace << "PASS 2 : backtrack\n";
|
||||
|
||||
// fill rem with any component removed,
|
||||
auto i = h.find(curr);
|
||||
auto i = h.find(curr);
|
||||
assert(i != h.end());
|
||||
|
||||
sscc.rem().push_front(curr);
|
||||
|
|
@ -449,7 +449,7 @@ namespace spot
|
|||
{
|
||||
// removing states
|
||||
for (auto j: sscc.rem())
|
||||
h[j] = -1;
|
||||
h[j] = -1;
|
||||
dec_depth(sscc.rem().size());
|
||||
sscc.pop();
|
||||
}
|
||||
|
|
@ -498,10 +498,10 @@ namespace spot
|
|||
inc_depth();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest->destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
dest->destroy();
|
||||
}
|
||||
|
||||
// If we have reached a dead component, ignore it.
|
||||
if (i->second == -1)
|
||||
|
|
@ -509,12 +509,12 @@ namespace spot
|
|||
|
||||
//self loop state
|
||||
if (!curr->compare(i->first))
|
||||
if (t->is_livelock_accepting_state(curr))
|
||||
{
|
||||
clear(h, todo, ta_init_it_);
|
||||
trace << "PASS 2: SUCCESS\n";
|
||||
return true;
|
||||
}
|
||||
if (t->is_livelock_accepting_state(curr))
|
||||
{
|
||||
clear(h, todo, ta_init_it_);
|
||||
trace << "PASS 2: SUCCESS\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Now this is the most interesting case. We have reached a
|
||||
// state S1 which is already part of a non-dead SSCC. Any such
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace spot
|
|||
namespace
|
||||
{
|
||||
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
|
||||
|
|
@ -111,7 +111,7 @@ namespace spot
|
|||
/// this heuristic is described in the paper cited above
|
||||
bool
|
||||
check(bool disable_second_pass = false,
|
||||
bool disable_heuristic_for_livelock_detection = false);
|
||||
bool disable_heuristic_for_livelock_detection = false);
|
||||
|
||||
/// \brief Check whether the product automaton contains
|
||||
/// a livelock-accepting run
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ namespace spot
|
|||
{
|
||||
static std::ostream&
|
||||
dump_hash_set(const hash_set* hs,
|
||||
const const_ta_ptr& aut,
|
||||
std::ostream& out)
|
||||
const const_ta_ptr& aut,
|
||||
std::ostream& out)
|
||||
{
|
||||
out << '{';
|
||||
const char* sep = "";
|
||||
|
|
@ -73,7 +73,7 @@ namespace spot
|
|||
// automaton
|
||||
static void
|
||||
build_result(const const_ta_ptr& a, std::list<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 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;
|
||||
unsigned num = 0;
|
||||
for (sit = sets.begin(); sit != sets.end(); ++sit)
|
||||
{
|
||||
hash_set::iterator hit;
|
||||
hash_set* h = *sit;
|
||||
for (hit = h->begin(); hit != h->end(); ++hit)
|
||||
state_num[*hit] = num;
|
||||
result_tgba->new_state();
|
||||
++num;
|
||||
}
|
||||
{
|
||||
hash_set::iterator hit;
|
||||
hash_set* h = *sit;
|
||||
for (hit = h->begin(); hit != h->end(); ++hit)
|
||||
state_num[*hit] = num;
|
||||
result_tgba->new_state();
|
||||
++num;
|
||||
}
|
||||
|
||||
// For each transition in the initial automaton, add the corresponding
|
||||
// transition in ta.
|
||||
|
||||
for (sit = sets.begin(); sit != sets.end(); ++sit)
|
||||
{
|
||||
hash_set::iterator hit;
|
||||
hash_set* h = *sit;
|
||||
hit = h->begin();
|
||||
const state* src = *hit;
|
||||
unsigned src_num = state_num[src];
|
||||
{
|
||||
hash_set::iterator hit;
|
||||
hash_set* h = *sit;
|
||||
hit = h->begin();
|
||||
const state* src = *hit;
|
||||
unsigned src_num = state_num[src];
|
||||
|
||||
bdd tgba_condition = bddtrue;
|
||||
bool is_initial_state = a->is_initial_state(src);
|
||||
if (!a->get_artificial_initial_state() && is_initial_state)
|
||||
tgba_condition = a->get_state_condition(src);
|
||||
bool is_accepting_state = a->is_accepting_state(src);
|
||||
bool is_livelock_accepting_state =
|
||||
a->is_livelock_accepting_state(src);
|
||||
bdd tgba_condition = bddtrue;
|
||||
bool is_initial_state = a->is_initial_state(src);
|
||||
if (!a->get_artificial_initial_state() && is_initial_state)
|
||||
tgba_condition = a->get_state_condition(src);
|
||||
bool is_accepting_state = a->is_accepting_state(src);
|
||||
bool is_livelock_accepting_state =
|
||||
a->is_livelock_accepting_state(src);
|
||||
|
||||
state_ta_explicit* new_src =
|
||||
new state_ta_explicit(result_tgba->state_from_number(src_num),
|
||||
tgba_condition, is_initial_state,
|
||||
is_accepting_state,
|
||||
is_livelock_accepting_state);
|
||||
state_ta_explicit* new_src =
|
||||
new state_ta_explicit(result_tgba->state_from_number(src_num),
|
||||
tgba_condition, is_initial_state,
|
||||
is_accepting_state,
|
||||
is_livelock_accepting_state);
|
||||
|
||||
state_ta_explicit* ta_src = result->add_state(new_src);
|
||||
state_ta_explicit* ta_src = result->add_state(new_src);
|
||||
|
||||
if (ta_src != new_src)
|
||||
{
|
||||
delete new_src;
|
||||
}
|
||||
else if (a->get_artificial_initial_state())
|
||||
{
|
||||
if (a->get_artificial_initial_state() == src)
|
||||
result->set_artificial_initial_state(new_src);
|
||||
}
|
||||
else if (is_initial_state)
|
||||
{
|
||||
result->add_to_initial_states_set(new_src);
|
||||
}
|
||||
if (ta_src != new_src)
|
||||
{
|
||||
delete new_src;
|
||||
}
|
||||
else if (a->get_artificial_initial_state())
|
||||
{
|
||||
if (a->get_artificial_initial_state() == src)
|
||||
result->set_artificial_initial_state(new_src);
|
||||
}
|
||||
else if (is_initial_state)
|
||||
{
|
||||
result->add_to_initial_states_set(new_src);
|
||||
}
|
||||
|
||||
ta_succ_iterator* succit = a->succ_iter(src);
|
||||
ta_succ_iterator* succit = a->succ_iter(src);
|
||||
|
||||
for (succit->first(); !succit->done(); succit->next())
|
||||
{
|
||||
const state* dst = succit->dst();
|
||||
hash_map::const_iterator i = state_num.find(dst);
|
||||
for (succit->first(); !succit->done(); succit->next())
|
||||
{
|
||||
const state* dst = succit->dst();
|
||||
hash_map::const_iterator i = state_num.find(dst);
|
||||
|
||||
if (i == state_num.end()) // Ignore useless destinations.
|
||||
continue;
|
||||
if (i == state_num.end()) // Ignore useless destinations.
|
||||
continue;
|
||||
|
||||
bdd tgba_condition = bddtrue;
|
||||
is_initial_state = a->is_initial_state(dst);
|
||||
if (!a->get_artificial_initial_state() && is_initial_state)
|
||||
tgba_condition = a->get_state_condition(dst);
|
||||
bool is_accepting_state = a->is_accepting_state(dst);
|
||||
bool is_livelock_accepting_state =
|
||||
a->is_livelock_accepting_state(dst);
|
||||
bdd tgba_condition = bddtrue;
|
||||
is_initial_state = a->is_initial_state(dst);
|
||||
if (!a->get_artificial_initial_state() && is_initial_state)
|
||||
tgba_condition = a->get_state_condition(dst);
|
||||
bool is_accepting_state = a->is_accepting_state(dst);
|
||||
bool is_livelock_accepting_state =
|
||||
a->is_livelock_accepting_state(dst);
|
||||
|
||||
state_ta_explicit* new_dst =
|
||||
new state_ta_explicit
|
||||
(result_tgba->state_from_number(i->second),
|
||||
tgba_condition, is_initial_state,
|
||||
is_accepting_state,
|
||||
is_livelock_accepting_state);
|
||||
state_ta_explicit* new_dst =
|
||||
new state_ta_explicit
|
||||
(result_tgba->state_from_number(i->second),
|
||||
tgba_condition, is_initial_state,
|
||||
is_accepting_state,
|
||||
is_livelock_accepting_state);
|
||||
|
||||
state_ta_explicit* ta_dst = result->add_state(new_dst);
|
||||
state_ta_explicit* ta_dst = result->add_state(new_dst);
|
||||
|
||||
if (ta_dst != new_dst)
|
||||
{
|
||||
delete new_dst;
|
||||
}
|
||||
else if (a->get_artificial_initial_state())
|
||||
{
|
||||
if (a->get_artificial_initial_state() == dst)
|
||||
result->set_artificial_initial_state(new_dst);
|
||||
}
|
||||
if (ta_dst != new_dst)
|
||||
{
|
||||
delete new_dst;
|
||||
}
|
||||
else if (a->get_artificial_initial_state())
|
||||
{
|
||||
if (a->get_artificial_initial_state() == dst)
|
||||
result->set_artificial_initial_state(new_dst);
|
||||
}
|
||||
|
||||
else if (is_initial_state)
|
||||
result->add_to_initial_states_set(new_dst);
|
||||
else if (is_initial_state)
|
||||
result->add_to_initial_states_set(new_dst);
|
||||
|
||||
result->create_transition
|
||||
(ta_src, succit->cond(),
|
||||
succit->acc(),
|
||||
ta_dst);
|
||||
}
|
||||
delete succit;
|
||||
}
|
||||
result->create_transition
|
||||
(ta_src, succit->cond(),
|
||||
succit->acc(),
|
||||
ta_dst);
|
||||
}
|
||||
delete succit;
|
||||
}
|
||||
}
|
||||
|
||||
static partition_t
|
||||
|
|
@ -187,22 +187,22 @@ namespace spot
|
|||
unsigned num_sets = ta_->acc().num_sets();
|
||||
std::map<acc_cond::mark_t, bdd> m2b;
|
||||
int acc_vars = ta_->get_dict()->register_anonymous_variables(num_sets,
|
||||
&m2b);
|
||||
&m2b);
|
||||
auto mark_to_bdd = [&](acc_cond::mark_t m) -> bdd
|
||||
{
|
||||
auto i = m2b.find(m);
|
||||
if (i != m2b.end())
|
||||
return i->second;
|
||||
{
|
||||
auto i = m2b.find(m);
|
||||
if (i != m2b.end())
|
||||
return i->second;
|
||||
|
||||
bdd res = bddtrue;
|
||||
for (unsigned n = 0; n < num_sets; ++n)
|
||||
if (m.has(n))
|
||||
res &= bdd_ithvar(acc_vars + n);
|
||||
else
|
||||
res &= bdd_nithvar(acc_vars + n);
|
||||
m2b.emplace_hint(i, m, res);
|
||||
return res;
|
||||
};
|
||||
bdd res = bddtrue;
|
||||
for (unsigned n = 0; n < num_sets; ++n)
|
||||
if (m.has(n))
|
||||
res &= bdd_ithvar(acc_vars + n);
|
||||
else
|
||||
res &= bdd_nithvar(acc_vars + n);
|
||||
m2b.emplace_hint(i, m, res);
|
||||
return res;
|
||||
};
|
||||
|
||||
partition_t cur_run;
|
||||
partition_t next_run;
|
||||
|
|
@ -231,22 +231,22 @@ namespace spot
|
|||
auto artificial_initial_state = ta_->get_artificial_initial_state();
|
||||
|
||||
for (it = states_set.begin(); it != states_set.end(); ++it)
|
||||
{
|
||||
const state* s = *it;
|
||||
if (s == artificial_initial_state)
|
||||
I->insert(s);
|
||||
else if (!artificial_initial_state && ta_->is_initial_state(s))
|
||||
I->insert(s);
|
||||
else if (ta_->is_livelock_accepting_state(s)
|
||||
&& ta_->is_accepting_state(s))
|
||||
G_F->insert(s);
|
||||
else if (ta_->is_accepting_state(s))
|
||||
F->insert(s);
|
||||
else if (ta_->is_livelock_accepting_state(s))
|
||||
G->insert(s);
|
||||
else
|
||||
S->insert(s);
|
||||
}
|
||||
{
|
||||
const state* s = *it;
|
||||
if (s == artificial_initial_state)
|
||||
I->insert(s);
|
||||
else if (!artificial_initial_state && ta_->is_initial_state(s))
|
||||
I->insert(s);
|
||||
else if (ta_->is_livelock_accepting_state(s)
|
||||
&& ta_->is_accepting_state(s))
|
||||
G_F->insert(s);
|
||||
else if (ta_->is_accepting_state(s))
|
||||
F->insert(s);
|
||||
else if (ta_->is_livelock_accepting_state(s))
|
||||
G->insert(s);
|
||||
else
|
||||
S->insert(s);
|
||||
}
|
||||
|
||||
hash_map state_set_map;
|
||||
|
||||
|
|
@ -255,103 +255,103 @@ namespace spot
|
|||
// Use bdd variables to number sets. set_num is the first variable
|
||||
// available.
|
||||
unsigned set_num =
|
||||
ta_->get_dict()->register_anonymous_variables(size, &m2b);
|
||||
ta_->get_dict()->register_anonymous_variables(size, &m2b);
|
||||
|
||||
std::set<int> free_var;
|
||||
for (unsigned i = set_num; i < set_num + size; ++i)
|
||||
free_var.insert(i);
|
||||
free_var.insert(i);
|
||||
std::map<int, int> used_var;
|
||||
|
||||
for (hash_set::const_iterator i = I->begin(); i != I->end(); ++i)
|
||||
{
|
||||
hash_set* cI = new hash_set;
|
||||
cI->insert(*i);
|
||||
done.push_back(cI);
|
||||
{
|
||||
hash_set* cI = new hash_set;
|
||||
cI->insert(*i);
|
||||
done.push_back(cI);
|
||||
|
||||
used_var[set_num] = 1;
|
||||
free_var.erase(set_num);
|
||||
state_set_map[*i] = set_num;
|
||||
++set_num;
|
||||
used_var[set_num] = 1;
|
||||
free_var.erase(set_num);
|
||||
state_set_map[*i] = set_num;
|
||||
++set_num;
|
||||
|
||||
}
|
||||
}
|
||||
delete I;
|
||||
|
||||
if (!G->empty())
|
||||
{
|
||||
unsigned s = G->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(G);
|
||||
else
|
||||
done.push_back(G);
|
||||
for (hash_set::const_iterator i = G->begin(); i != G->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
{
|
||||
unsigned s = G->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(G);
|
||||
else
|
||||
done.push_back(G);
|
||||
for (hash_set::const_iterator i = G->begin(); i != G->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete G;
|
||||
}
|
||||
{
|
||||
delete G;
|
||||
}
|
||||
|
||||
if (!F->empty())
|
||||
{
|
||||
unsigned s = F->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(F);
|
||||
else
|
||||
done.push_back(F);
|
||||
for (hash_set::const_iterator i = F->begin(); i != F->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
{
|
||||
unsigned s = F->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(F);
|
||||
else
|
||||
done.push_back(F);
|
||||
for (hash_set::const_iterator i = F->begin(); i != F->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete F;
|
||||
}
|
||||
{
|
||||
delete F;
|
||||
}
|
||||
|
||||
if (!G_F->empty())
|
||||
{
|
||||
unsigned s = G_F->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(G_F);
|
||||
else
|
||||
done.push_back(G_F);
|
||||
for (hash_set::const_iterator i = G_F->begin(); i != G_F->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
{
|
||||
unsigned s = G_F->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(G_F);
|
||||
else
|
||||
done.push_back(G_F);
|
||||
for (hash_set::const_iterator i = G_F->begin(); i != G_F->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete G_F;
|
||||
}
|
||||
{
|
||||
delete G_F;
|
||||
}
|
||||
|
||||
if (!S->empty())
|
||||
{
|
||||
unsigned s = S->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(S);
|
||||
else
|
||||
done.push_back(S);
|
||||
for (hash_set::const_iterator i = S->begin(); i != S->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
{
|
||||
unsigned s = S->size();
|
||||
unsigned num = set_num;
|
||||
++set_num;
|
||||
used_var[num] = s;
|
||||
free_var.erase(num);
|
||||
if (s > 1)
|
||||
cur_run.push_back(S);
|
||||
else
|
||||
done.push_back(S);
|
||||
for (hash_set::const_iterator i = S->begin(); i != S->end(); ++i)
|
||||
state_set_map[*i] = num;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete S;
|
||||
}
|
||||
{
|
||||
delete S;
|
||||
}
|
||||
|
||||
|
||||
// A bdd_states_map is a list of formulae (in a BDD form)
|
||||
|
|
@ -366,132 +366,132 @@ namespace spot
|
|||
bdd bdd_false_acceptance_condition = bdd_ithvar(num);
|
||||
|
||||
while (did_split)
|
||||
{
|
||||
did_split = false;
|
||||
while (!cur_run.empty())
|
||||
{
|
||||
// Get a set to process.
|
||||
hash_set* cur = cur_run.front();
|
||||
cur_run.pop_front();
|
||||
{
|
||||
did_split = false;
|
||||
while (!cur_run.empty())
|
||||
{
|
||||
// Get a set to process.
|
||||
hash_set* cur = cur_run.front();
|
||||
cur_run.pop_front();
|
||||
|
||||
trace
|
||||
<< "processing " << format_hash_set(cur, ta_) << std::endl;
|
||||
trace
|
||||
<< "processing " << format_hash_set(cur, ta_) << std::endl;
|
||||
|
||||
hash_set::iterator hi;
|
||||
bdd_states_map bdd_map;
|
||||
for (hi = cur->begin(); hi != cur->end(); ++hi)
|
||||
{
|
||||
const state* src = *hi;
|
||||
bdd f = bddfalse;
|
||||
ta_succ_iterator* si = ta_->succ_iter(src);
|
||||
trace << "+src: " << src << std::endl;
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
const state* dst = si->dst();
|
||||
hash_map::const_iterator i = state_set_map.find(dst);
|
||||
hash_set::iterator hi;
|
||||
bdd_states_map bdd_map;
|
||||
for (hi = cur->begin(); hi != cur->end(); ++hi)
|
||||
{
|
||||
const state* src = *hi;
|
||||
bdd f = bddfalse;
|
||||
ta_succ_iterator* si = ta_->succ_iter(src);
|
||||
trace << "+src: " << src << std::endl;
|
||||
for (si->first(); !si->done(); si->next())
|
||||
{
|
||||
const state* dst = si->dst();
|
||||
hash_map::const_iterator i = state_set_map.find(dst);
|
||||
|
||||
assert(i != state_set_map.end());
|
||||
auto curacc =
|
||||
mark_to_bdd(si->acc());
|
||||
f |= (bdd_ithvar(i->second)
|
||||
& si->cond() & curacc);
|
||||
trace
|
||||
<< "+f: " << bdd_format_accset(ta_->get_dict(), f)
|
||||
<< "\n -bdd_ithvar(i->second): "
|
||||
<< bdd_format_accset(ta_->get_dict(),
|
||||
bdd_ithvar(i->second))
|
||||
<< "\n -si->cond(): "
|
||||
<< bdd_format_accset(ta_->get_dict(),
|
||||
si->cond())
|
||||
<< "\n -current_acceptance_conditions: "
|
||||
<< si->acc()
|
||||
<< std::endl;
|
||||
}
|
||||
delete si;
|
||||
assert(i != state_set_map.end());
|
||||
auto curacc =
|
||||
mark_to_bdd(si->acc());
|
||||
f |= (bdd_ithvar(i->second)
|
||||
& si->cond() & curacc);
|
||||
trace
|
||||
<< "+f: " << bdd_format_accset(ta_->get_dict(), f)
|
||||
<< "\n -bdd_ithvar(i->second): "
|
||||
<< bdd_format_accset(ta_->get_dict(),
|
||||
bdd_ithvar(i->second))
|
||||
<< "\n -si->cond(): "
|
||||
<< bdd_format_accset(ta_->get_dict(),
|
||||
si->cond())
|
||||
<< "\n -current_acceptance_conditions: "
|
||||
<< si->acc()
|
||||
<< std::endl;
|
||||
}
|
||||
delete si;
|
||||
|
||||
// Have we already seen this formula ?
|
||||
bdd_states_map::iterator bsi = bdd_map.find(f);
|
||||
if (bsi == bdd_map.end())
|
||||
{
|
||||
// No, create a new set.
|
||||
hash_set* new_set = new hash_set;
|
||||
new_set->insert(src);
|
||||
bdd_map[f] = new_set;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Yes, add the current state to the set.
|
||||
bsi->second->insert(src);
|
||||
}
|
||||
}
|
||||
// Have we already seen this formula ?
|
||||
bdd_states_map::iterator bsi = bdd_map.find(f);
|
||||
if (bsi == bdd_map.end())
|
||||
{
|
||||
// No, create a new set.
|
||||
hash_set* new_set = new hash_set;
|
||||
new_set->insert(src);
|
||||
bdd_map[f] = new_set;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Yes, add the current state to the set.
|
||||
bsi->second->insert(src);
|
||||
}
|
||||
}
|
||||
|
||||
bdd_states_map::iterator bsi = bdd_map.begin();
|
||||
if (bdd_map.size() == 1)
|
||||
{
|
||||
// The set was not split.
|
||||
trace
|
||||
<< "set " << format_hash_set(bsi->second, ta_)
|
||||
<< " was not split" << std::endl;
|
||||
next_run.push_back(bsi->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
did_split = true;
|
||||
for (; bsi != bdd_map.end(); ++bsi)
|
||||
{
|
||||
hash_set* set = bsi->second;
|
||||
// Free the number associated to these states.
|
||||
unsigned num = state_set_map[*set->begin()];
|
||||
assert(used_var.find(num) != used_var.end());
|
||||
unsigned left = (used_var[num] -= set->size());
|
||||
// Make sure LEFT does not become negative
|
||||
// (hence bigger than SIZE when read as unsigned)
|
||||
assert(left < size);
|
||||
if (left == 0)
|
||||
{
|
||||
used_var.erase(num);
|
||||
free_var.insert(num);
|
||||
}
|
||||
// Pick a free number
|
||||
assert(!free_var.empty());
|
||||
num = *free_var.begin();
|
||||
free_var.erase(free_var.begin());
|
||||
used_var[num] = set->size();
|
||||
for (hash_set::iterator hit = set->begin();
|
||||
hit != set->end(); ++hit)
|
||||
state_set_map[*hit] = num;
|
||||
// Trivial sets can't be splitted any further.
|
||||
if (set->size() == 1)
|
||||
{
|
||||
trace
|
||||
<< "set " << format_hash_set(set, ta_)
|
||||
<< " is minimal" << std::endl;
|
||||
done.push_back(set);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace
|
||||
<< "set " << format_hash_set(set, ta_)
|
||||
<< " should be processed further" << std::endl;
|
||||
next_run.push_back(set);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete cur;
|
||||
}
|
||||
if (did_split)
|
||||
trace
|
||||
<< "splitting did occur during this pass." << std::endl;
|
||||
bdd_states_map::iterator bsi = bdd_map.begin();
|
||||
if (bdd_map.size() == 1)
|
||||
{
|
||||
// The set was not split.
|
||||
trace
|
||||
<< "set " << format_hash_set(bsi->second, ta_)
|
||||
<< " was not split" << std::endl;
|
||||
next_run.push_back(bsi->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
did_split = true;
|
||||
for (; bsi != bdd_map.end(); ++bsi)
|
||||
{
|
||||
hash_set* set = bsi->second;
|
||||
// Free the number associated to these states.
|
||||
unsigned num = state_set_map[*set->begin()];
|
||||
assert(used_var.find(num) != used_var.end());
|
||||
unsigned left = (used_var[num] -= set->size());
|
||||
// Make sure LEFT does not become negative
|
||||
// (hence bigger than SIZE when read as unsigned)
|
||||
assert(left < size);
|
||||
if (left == 0)
|
||||
{
|
||||
used_var.erase(num);
|
||||
free_var.insert(num);
|
||||
}
|
||||
// Pick a free number
|
||||
assert(!free_var.empty());
|
||||
num = *free_var.begin();
|
||||
free_var.erase(free_var.begin());
|
||||
used_var[num] = set->size();
|
||||
for (hash_set::iterator hit = set->begin();
|
||||
hit != set->end(); ++hit)
|
||||
state_set_map[*hit] = num;
|
||||
// Trivial sets can't be splitted any further.
|
||||
if (set->size() == 1)
|
||||
{
|
||||
trace
|
||||
<< "set " << format_hash_set(set, ta_)
|
||||
<< " is minimal" << std::endl;
|
||||
done.push_back(set);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace
|
||||
<< "set " << format_hash_set(set, ta_)
|
||||
<< " should be processed further" << std::endl;
|
||||
next_run.push_back(set);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete cur;
|
||||
}
|
||||
if (did_split)
|
||||
trace
|
||||
<< "splitting did occur during this pass." << std::endl;
|
||||
|
||||
std::swap(cur_run, next_run);
|
||||
}
|
||||
std::swap(cur_run, next_run);
|
||||
}
|
||||
|
||||
done.splice(done.end(), cur_run);
|
||||
|
||||
#ifdef TRACE
|
||||
trace << "Final partition: ";
|
||||
for (partition_t::const_iterator i = done.begin(); i != done.end(); ++i)
|
||||
trace << format_hash_set(*i, ta_) << ' ';
|
||||
trace << format_hash_set(*i, ta_) << ' ';
|
||||
trace << std::endl;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -51,17 +51,17 @@ namespace spot
|
|||
{
|
||||
|
||||
if (artificial_livelock_acc_state)
|
||||
{
|
||||
auto artificial_livelock_acc_state_added =
|
||||
{
|
||||
auto artificial_livelock_acc_state_added =
|
||||
testing_automata->add_state(artificial_livelock_acc_state);
|
||||
|
||||
// unique artificial_livelock_acc_state
|
||||
assert(artificial_livelock_acc_state_added
|
||||
== artificial_livelock_acc_state);
|
||||
(void)artificial_livelock_acc_state_added;
|
||||
artificial_livelock_acc_state->set_livelock_accepting_state(true);
|
||||
artificial_livelock_acc_state->free_transitions();
|
||||
}
|
||||
// unique artificial_livelock_acc_state
|
||||
assert(artificial_livelock_acc_state_added
|
||||
== artificial_livelock_acc_state);
|
||||
(void)artificial_livelock_acc_state_added;
|
||||
artificial_livelock_acc_state->set_livelock_accepting_state(true);
|
||||
artificial_livelock_acc_state->free_transitions();
|
||||
}
|
||||
|
||||
ta::states_set_t states_set = testing_automata->get_states_set();
|
||||
ta::states_set_t::iterator it;
|
||||
|
|
@ -70,86 +70,86 @@ namespace spot
|
|||
new state_ta_explicit::transitions;
|
||||
|
||||
for (it = states_set.begin(); it != states_set.end(); ++it)
|
||||
{
|
||||
auto source = const_cast<state_ta_explicit*>
|
||||
(static_cast<const state_ta_explicit*>(*it));
|
||||
{
|
||||
auto source = const_cast<state_ta_explicit*>
|
||||
(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::iterator it_trans;
|
||||
state_ta_explicit::transitions* trans = source->get_transitions();
|
||||
state_ta_explicit::transitions::iterator it_trans;
|
||||
|
||||
if (trans)
|
||||
for (it_trans = trans->begin(); it_trans != trans->end();)
|
||||
{
|
||||
auto dest = const_cast<state_ta_explicit*>((*it_trans)->dest);
|
||||
if (trans)
|
||||
for (it_trans = trans->begin(); it_trans != trans->end();)
|
||||
{
|
||||
auto dest = const_cast<state_ta_explicit*>((*it_trans)->dest);
|
||||
|
||||
state_ta_explicit::transitions* dest_trans =
|
||||
dest->get_transitions();
|
||||
bool dest_trans_empty = !dest_trans || dest_trans->empty();
|
||||
state_ta_explicit::transitions* dest_trans =
|
||||
dest->get_transitions();
|
||||
bool dest_trans_empty = !dest_trans || dest_trans->empty();
|
||||
|
||||
//select transitions where a destination is a livelock state
|
||||
// which isn't a Buchi accepting state and has successors
|
||||
if (dest->is_livelock_accepting_state()
|
||||
&& (!dest->is_accepting_state()) && (!dest_trans_empty))
|
||||
transitions_to_livelock_states->push_front(*it_trans);
|
||||
//select transitions where a destination is a livelock state
|
||||
// which isn't a Buchi accepting state and has successors
|
||||
if (dest->is_livelock_accepting_state()
|
||||
&& (!dest->is_accepting_state()) && (!dest_trans_empty))
|
||||
transitions_to_livelock_states->push_front(*it_trans);
|
||||
|
||||
// optimization to have, after minimization, an unique
|
||||
// livelock state which has no successors
|
||||
if (dest->is_livelock_accepting_state() && (dest_trans_empty))
|
||||
dest->set_accepting_state(false);
|
||||
// optimization to have, after minimization, an unique
|
||||
// livelock state which has no successors
|
||||
if (dest->is_livelock_accepting_state() && (dest_trans_empty))
|
||||
dest->set_accepting_state(false);
|
||||
|
||||
++it_trans;
|
||||
}
|
||||
++it_trans;
|
||||
}
|
||||
|
||||
if (transitions_to_livelock_states)
|
||||
{
|
||||
state_ta_explicit::transitions::iterator it_trans;
|
||||
if (transitions_to_livelock_states)
|
||||
{
|
||||
state_ta_explicit::transitions::iterator it_trans;
|
||||
|
||||
for (it_trans = transitions_to_livelock_states->begin();
|
||||
it_trans != transitions_to_livelock_states->end();
|
||||
++it_trans)
|
||||
{
|
||||
if (artificial_livelock_acc_state)
|
||||
{
|
||||
testing_automata->create_transition
|
||||
(source,
|
||||
(*it_trans)->condition,
|
||||
(*it_trans)->acceptance_conditions,
|
||||
artificial_livelock_acc_state, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
testing_automata->create_transition
|
||||
(source,
|
||||
(*it_trans)->condition,
|
||||
(*it_trans)->acceptance_conditions,
|
||||
((*it_trans)->dest)->stuttering_reachable_livelock,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (it_trans = transitions_to_livelock_states->begin();
|
||||
it_trans != transitions_to_livelock_states->end();
|
||||
++it_trans)
|
||||
{
|
||||
if (artificial_livelock_acc_state)
|
||||
{
|
||||
testing_automata->create_transition
|
||||
(source,
|
||||
(*it_trans)->condition,
|
||||
(*it_trans)->acceptance_conditions,
|
||||
artificial_livelock_acc_state, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
testing_automata->create_transition
|
||||
(source,
|
||||
(*it_trans)->condition,
|
||||
(*it_trans)->acceptance_conditions,
|
||||
((*it_trans)->dest)->stuttering_reachable_livelock,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete transitions_to_livelock_states;
|
||||
|
||||
for (it = states_set.begin(); it != states_set.end(); ++it)
|
||||
{
|
||||
state_ta_explicit* state = static_cast<state_ta_explicit*> (*it);
|
||||
state_ta_explicit::transitions* state_trans =
|
||||
{
|
||||
state_ta_explicit* state = static_cast<state_ta_explicit*> (*it);
|
||||
state_ta_explicit::transitions* state_trans =
|
||||
(state)->get_transitions();
|
||||
bool state_trans_empty = !state_trans || state_trans->empty();
|
||||
bool state_trans_empty = !state_trans || state_trans->empty();
|
||||
|
||||
if (state->is_livelock_accepting_state()
|
||||
&& (!state->is_accepting_state()) && (!state_trans_empty))
|
||||
state->set_livelock_accepting_state(false);
|
||||
}
|
||||
if (state->is_livelock_accepting_state()
|
||||
&& (!state->is_accepting_state()) && (!state_trans_empty))
|
||||
state->set_livelock_accepting_state(false);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
compute_livelock_acceptance_states(const ta_explicit_ptr& testing_aut,
|
||||
bool single_pass_emptiness_check,
|
||||
state_ta_explicit*
|
||||
artificial_livelock_acc_state)
|
||||
bool single_pass_emptiness_check,
|
||||
state_ta_explicit*
|
||||
artificial_livelock_acc_state)
|
||||
{
|
||||
// We use five main data in this algorithm:
|
||||
// * sscc: a stack of strongly stuttering-connected components (SSCC)
|
||||
|
|
@ -177,234 +177,234 @@ namespace spot
|
|||
std::stack<const state*> init_set;
|
||||
|
||||
for (auto s: testing_aut->get_initial_states_set())
|
||||
init_set.push(s);
|
||||
init_set.push(s);
|
||||
|
||||
while (!init_set.empty())
|
||||
{
|
||||
// Setup depth-first search from initial states.
|
||||
{
|
||||
// Setup depth-first search from initial states.
|
||||
|
||||
{
|
||||
auto init = down_cast<const state_ta_explicit*> (init_set.top());
|
||||
init_set.pop();
|
||||
{
|
||||
auto init = down_cast<const state_ta_explicit*> (init_set.top());
|
||||
init_set.pop();
|
||||
|
||||
if (!h.emplace(init, num + 1).second)
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
if (!h.emplace(init, num + 1).second)
|
||||
{
|
||||
init->destroy();
|
||||
continue;
|
||||
}
|
||||
|
||||
sscc.push(++num);
|
||||
arc.push(0U);
|
||||
sscc.top().is_accepting
|
||||
sscc.push(++num);
|
||||
arc.push(0U);
|
||||
sscc.top().is_accepting
|
||||
= testing_aut->is_accepting_state(init);
|
||||
twa_succ_iterator* iter = testing_aut->succ_iter(init);
|
||||
iter->first();
|
||||
todo.emplace(init, iter);
|
||||
}
|
||||
twa_succ_iterator* iter = testing_aut->succ_iter(init);
|
||||
iter->first();
|
||||
todo.emplace(init, iter);
|
||||
}
|
||||
|
||||
while (!todo.empty())
|
||||
{
|
||||
auto curr = todo.top().first;
|
||||
while (!todo.empty())
|
||||
{
|
||||
auto curr = todo.top().first;
|
||||
|
||||
auto i = h.find(curr);
|
||||
// If we have reached a dead component, ignore it.
|
||||
if (i != h.end() && i->second == -1)
|
||||
{
|
||||
todo.pop();
|
||||
continue;
|
||||
}
|
||||
auto i = h.find(curr);
|
||||
// If we have reached a dead component, ignore it.
|
||||
if (i != h.end() && i->second == -1)
|
||||
{
|
||||
todo.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
// We are looking at the next successor in SUCC.
|
||||
twa_succ_iterator* succ = todo.top().second;
|
||||
// We are looking at the next successor in SUCC.
|
||||
twa_succ_iterator* succ = todo.top().second;
|
||||
|
||||
// If there is no more successor, backtrack.
|
||||
if (succ->done())
|
||||
{
|
||||
// We have explored all successors of state CURR.
|
||||
// If there is no more successor, backtrack.
|
||||
if (succ->done())
|
||||
{
|
||||
// We have explored all successors of state CURR.
|
||||
|
||||
// Backtrack TODO.
|
||||
todo.pop();
|
||||
// Backtrack TODO.
|
||||
todo.pop();
|
||||
|
||||
// fill rem with any component removed,
|
||||
assert(i != h.end());
|
||||
sscc.rem().push_front(curr);
|
||||
// fill rem with any component removed,
|
||||
assert(i != h.end());
|
||||
sscc.rem().push_front(curr);
|
||||
|
||||
// When backtracking the root of an SSCC, we must also
|
||||
// remove that SSCC from the ROOT stacks. We must
|
||||
// discard from H all reachable states from this SSCC.
|
||||
assert(!sscc.empty());
|
||||
if (sscc.top().index == i->second)
|
||||
{
|
||||
// removing states
|
||||
bool is_livelock_accepting_sscc = (sscc.rem().size() > 1)
|
||||
&& ((sscc.top().is_accepting) ||
|
||||
(testing_aut->acc().
|
||||
accepting(sscc.top().condition)));
|
||||
trace << "*** sscc.size() = ***" << sscc.size() << '\n';
|
||||
for (auto j: sscc.rem())
|
||||
{
|
||||
h[j] = -1;
|
||||
// When backtracking the root of an SSCC, we must also
|
||||
// remove that SSCC from the ROOT stacks. We must
|
||||
// discard from H all reachable states from this SSCC.
|
||||
assert(!sscc.empty());
|
||||
if (sscc.top().index == i->second)
|
||||
{
|
||||
// removing states
|
||||
bool is_livelock_accepting_sscc = (sscc.rem().size() > 1)
|
||||
&& ((sscc.top().is_accepting) ||
|
||||
(testing_aut->acc().
|
||||
accepting(sscc.top().condition)));
|
||||
trace << "*** sscc.size() = ***" << sscc.size() << '\n';
|
||||
for (auto j: sscc.rem())
|
||||
{
|
||||
h[j] = -1;
|
||||
|
||||
if (is_livelock_accepting_sscc)
|
||||
{
|
||||
// if it is an accepting sscc add the state to
|
||||
// G (=the livelock-accepting states set)
|
||||
trace << "*** sscc.size() > 1: states: ***"
|
||||
<< testing_aut->format_state(j)
|
||||
<< '\n';
|
||||
auto livelock_accepting_state =
|
||||
const_cast<state_ta_explicit*>
|
||||
(down_cast<const state_ta_explicit*>(j));
|
||||
if (is_livelock_accepting_sscc)
|
||||
{
|
||||
// if it is an accepting sscc add the state to
|
||||
// G (=the livelock-accepting states set)
|
||||
trace << "*** sscc.size() > 1: states: ***"
|
||||
<< testing_aut->format_state(j)
|
||||
<< '\n';
|
||||
auto livelock_accepting_state =
|
||||
const_cast<state_ta_explicit*>
|
||||
(down_cast<const state_ta_explicit*>(j));
|
||||
|
||||
livelock_accepting_state->
|
||||
set_livelock_accepting_state(true);
|
||||
livelock_accepting_state->
|
||||
set_livelock_accepting_state(true);
|
||||
|
||||
if (single_pass_emptiness_check)
|
||||
{
|
||||
livelock_accepting_state
|
||||
->set_accepting_state(true);
|
||||
livelock_accepting_state
|
||||
->stuttering_reachable_livelock
|
||||
= livelock_accepting_state;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (single_pass_emptiness_check)
|
||||
{
|
||||
livelock_accepting_state
|
||||
->set_accepting_state(true);
|
||||
livelock_accepting_state
|
||||
->stuttering_reachable_livelock
|
||||
= livelock_accepting_state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(!arc.empty());
|
||||
sscc.pop();
|
||||
arc.pop();
|
||||
}
|
||||
assert(!arc.empty());
|
||||
sscc.pop();
|
||||
arc.pop();
|
||||
}
|
||||
|
||||
// automata reduction
|
||||
testing_aut->delete_stuttering_and_hole_successors(curr);
|
||||
// automata reduction
|
||||
testing_aut->delete_stuttering_and_hole_successors(curr);
|
||||
|
||||
delete succ;
|
||||
// Do not delete CURR: it is a key in H.
|
||||
continue;
|
||||
}
|
||||
delete succ;
|
||||
// Do not delete CURR: it is a key in H.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fetch the values destination state we are interested in...
|
||||
auto dest = succ->dst();
|
||||
// Fetch the values destination state we are interested in...
|
||||
auto dest = succ->dst();
|
||||
|
||||
auto acc_cond = succ->acc();
|
||||
// ... and point the iterator to the next successor, for
|
||||
// the next iteration.
|
||||
succ->next();
|
||||
// We do not need SUCC from now on.
|
||||
auto acc_cond = succ->acc();
|
||||
// ... and point the iterator to the next successor, for
|
||||
// the next iteration.
|
||||
succ->next();
|
||||
// We do not need SUCC from now on.
|
||||
|
||||
// Are we going to a new state through a stuttering transition?
|
||||
bool is_stuttering_transition =
|
||||
testing_aut->get_state_condition(curr)
|
||||
== testing_aut->get_state_condition(dest);
|
||||
auto id = h.find(dest);
|
||||
// Are we going to a new state through a stuttering transition?
|
||||
bool is_stuttering_transition =
|
||||
testing_aut->get_state_condition(curr)
|
||||
== testing_aut->get_state_condition(dest);
|
||||
auto id = h.find(dest);
|
||||
|
||||
// Is this a new state?
|
||||
if (id == h.end())
|
||||
{
|
||||
if (!is_stuttering_transition)
|
||||
{
|
||||
init_set.push(dest);
|
||||
dest->destroy();
|
||||
continue;
|
||||
}
|
||||
// Is this a new state?
|
||||
if (id == h.end())
|
||||
{
|
||||
if (!is_stuttering_transition)
|
||||
{
|
||||
init_set.push(dest);
|
||||
dest->destroy();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Number it, stack it, and register its successors
|
||||
// for later processing.
|
||||
h[dest] = ++num;
|
||||
sscc.push(num);
|
||||
arc.push(acc_cond);
|
||||
sscc.top().is_accepting =
|
||||
testing_aut->is_accepting_state(dest);
|
||||
// Number it, stack it, and register its successors
|
||||
// for later processing.
|
||||
h[dest] = ++num;
|
||||
sscc.push(num);
|
||||
arc.push(acc_cond);
|
||||
sscc.top().is_accepting =
|
||||
testing_aut->is_accepting_state(dest);
|
||||
|
||||
twa_succ_iterator* iter = testing_aut->succ_iter(dest);
|
||||
iter->first();
|
||||
todo.emplace(dest, iter);
|
||||
continue;
|
||||
}
|
||||
dest->destroy();
|
||||
twa_succ_iterator* iter = testing_aut->succ_iter(dest);
|
||||
iter->first();
|
||||
todo.emplace(dest, iter);
|
||||
continue;
|
||||
}
|
||||
dest->destroy();
|
||||
|
||||
// If we have reached a dead component, ignore it.
|
||||
if (id->second == -1)
|
||||
continue;
|
||||
// If we have reached a dead component, ignore it.
|
||||
if (id->second == -1)
|
||||
continue;
|
||||
|
||||
trace << "***compute_livelock_acceptance_states: CYCLE***\n";
|
||||
trace << "***compute_livelock_acceptance_states: CYCLE***\n";
|
||||
|
||||
if (!curr->compare(id->first))
|
||||
{
|
||||
auto self_loop_state = const_cast<state_ta_explicit*>
|
||||
(down_cast<const state_ta_explicit*>(curr));
|
||||
assert(self_loop_state);
|
||||
if (!curr->compare(id->first))
|
||||
{
|
||||
auto self_loop_state = const_cast<state_ta_explicit*>
|
||||
(down_cast<const state_ta_explicit*>(curr));
|
||||
assert(self_loop_state);
|
||||
|
||||
if (testing_aut->is_accepting_state(self_loop_state)
|
||||
|| (testing_aut->acc().accepting(acc_cond)))
|
||||
{
|
||||
self_loop_state->set_livelock_accepting_state(true);
|
||||
if (single_pass_emptiness_check)
|
||||
{
|
||||
self_loop_state->set_accepting_state(true);
|
||||
self_loop_state->stuttering_reachable_livelock
|
||||
= self_loop_state;
|
||||
}
|
||||
}
|
||||
if (testing_aut->is_accepting_state(self_loop_state)
|
||||
|| (testing_aut->acc().accepting(acc_cond)))
|
||||
{
|
||||
self_loop_state->set_livelock_accepting_state(true);
|
||||
if (single_pass_emptiness_check)
|
||||
{
|
||||
self_loop_state->set_accepting_state(true);
|
||||
self_loop_state->stuttering_reachable_livelock
|
||||
= self_loop_state;
|
||||
}
|
||||
}
|
||||
|
||||
trace
|
||||
<< "***compute_livelock_acceptance_states: CYCLE: "
|
||||
<< "self_loop_state***\n";
|
||||
}
|
||||
trace
|
||||
<< "***compute_livelock_acceptance_states: CYCLE: "
|
||||
<< "self_loop_state***\n";
|
||||
}
|
||||
|
||||
// Now this is the most interesting case. We have reached a
|
||||
// state S1 which is already part of a non-dead SSCC. Any such
|
||||
// non-dead SSCC has necessarily been crossed by our path to
|
||||
// this state: there is a state S2 in our path which belongs
|
||||
// to this SSCC too. We are going to merge all states between
|
||||
// this S1 and S2 into this SSCC.
|
||||
//
|
||||
// This merge is easy to do because the order of the SSCC in
|
||||
// ROOT is ascending: we just have to merge all SSCCs from the
|
||||
// top of ROOT that have an index greater to the one of
|
||||
// the SSCC of S2 (called the "threshold").
|
||||
int threshold = id->second;
|
||||
std::list<const state*> rem;
|
||||
bool acc = false;
|
||||
// Now this is the most interesting case. We have reached a
|
||||
// state S1 which is already part of a non-dead SSCC. Any such
|
||||
// non-dead SSCC has necessarily been crossed by our path to
|
||||
// this state: there is a state S2 in our path which belongs
|
||||
// to this SSCC too. We are going to merge all states between
|
||||
// this S1 and S2 into this SSCC.
|
||||
//
|
||||
// This merge is easy to do because the order of the SSCC in
|
||||
// ROOT is ascending: we just have to merge all SSCCs from the
|
||||
// top of ROOT that have an index greater to the one of
|
||||
// the SSCC of S2 (called the "threshold").
|
||||
int threshold = id->second;
|
||||
std::list<const state*> rem;
|
||||
bool acc = false;
|
||||
|
||||
while (threshold < sscc.top().index)
|
||||
{
|
||||
assert(!sscc.empty());
|
||||
assert(!arc.empty());
|
||||
acc |= sscc.top().is_accepting;
|
||||
acc_cond |= sscc.top().condition;
|
||||
acc_cond |= arc.top();
|
||||
rem.splice(rem.end(), sscc.rem());
|
||||
sscc.pop();
|
||||
arc.pop();
|
||||
}
|
||||
while (threshold < sscc.top().index)
|
||||
{
|
||||
assert(!sscc.empty());
|
||||
assert(!arc.empty());
|
||||
acc |= sscc.top().is_accepting;
|
||||
acc_cond |= sscc.top().condition;
|
||||
acc_cond |= arc.top();
|
||||
rem.splice(rem.end(), sscc.rem());
|
||||
sscc.pop();
|
||||
arc.pop();
|
||||
}
|
||||
|
||||
// Note that we do not always have
|
||||
// threshold == sscc.top().index
|
||||
// after this loop, the SSCC whose index is threshold might have
|
||||
// been merged with a lower SSCC.
|
||||
// Note that we do not always have
|
||||
// threshold == sscc.top().index
|
||||
// after this loop, the SSCC whose index is threshold might have
|
||||
// been merged with a lower SSCC.
|
||||
|
||||
// Accumulate all acceptance conditions into the merged SSCC.
|
||||
sscc.top().is_accepting |= acc;
|
||||
sscc.top().condition |= acc_cond;
|
||||
// Accumulate all acceptance conditions into the merged SSCC.
|
||||
sscc.top().is_accepting |= acc;
|
||||
sscc.top().condition |= acc_cond;
|
||||
|
||||
sscc.rem().splice(sscc.rem().end(), rem);
|
||||
sscc.rem().splice(sscc.rem().end(), rem);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (artificial_livelock_acc_state || single_pass_emptiness_check)
|
||||
transform_to_single_pass_automaton(testing_aut,
|
||||
artificial_livelock_acc_state);
|
||||
transform_to_single_pass_automaton(testing_aut,
|
||||
artificial_livelock_acc_state);
|
||||
}
|
||||
|
||||
ta_explicit_ptr
|
||||
build_ta(const ta_explicit_ptr& ta, bdd atomic_propositions_set_,
|
||||
bool degeneralized,
|
||||
bool single_pass_emptiness_check,
|
||||
bool artificial_livelock_state_mode,
|
||||
bool no_livelock)
|
||||
bool degeneralized,
|
||||
bool single_pass_emptiness_check,
|
||||
bool artificial_livelock_state_mode,
|
||||
bool no_livelock)
|
||||
{
|
||||
|
||||
std::stack<state_ta_explicit*> todo;
|
||||
|
|
@ -414,140 +414,140 @@ namespace spot
|
|||
auto tgba_init_state = tgba_->get_init_state();
|
||||
|
||||
bdd tgba_condition = [&]()
|
||||
{
|
||||
bdd cond = bddfalse;
|
||||
for (auto i: tgba_->succ(tgba_init_state))
|
||||
cond |= i->cond();
|
||||
return cond;
|
||||
}();
|
||||
{
|
||||
bdd cond = bddfalse;
|
||||
for (auto i: tgba_->succ(tgba_init_state))
|
||||
cond |= i->cond();
|
||||
return cond;
|
||||
}();
|
||||
|
||||
bool is_acc = false;
|
||||
if (degeneralized)
|
||||
{
|
||||
twa_succ_iterator* it = tgba_->succ_iter(tgba_init_state);
|
||||
it->first();
|
||||
if (!it->done())
|
||||
is_acc = it->acc() != 0U;
|
||||
delete it;
|
||||
}
|
||||
{
|
||||
twa_succ_iterator* it = tgba_->succ_iter(tgba_init_state);
|
||||
it->first();
|
||||
if (!it->done())
|
||||
is_acc = it->acc() != 0U;
|
||||
delete it;
|
||||
}
|
||||
|
||||
bdd satone_tgba_condition;
|
||||
while ((satone_tgba_condition = bdd_satoneset(tgba_condition,
|
||||
atomic_propositions_set_,
|
||||
bddtrue)) != bddfalse)
|
||||
{
|
||||
tgba_condition -= satone_tgba_condition;
|
||||
state_ta_explicit* init_state = new
|
||||
state_ta_explicit(tgba_init_state->clone(),
|
||||
satone_tgba_condition, true, is_acc);
|
||||
state_ta_explicit* s = ta->add_state(init_state);
|
||||
assert(s == init_state);
|
||||
ta->add_to_initial_states_set(s);
|
||||
atomic_propositions_set_,
|
||||
bddtrue)) != bddfalse)
|
||||
{
|
||||
tgba_condition -= satone_tgba_condition;
|
||||
state_ta_explicit* init_state = new
|
||||
state_ta_explicit(tgba_init_state->clone(),
|
||||
satone_tgba_condition, true, is_acc);
|
||||
state_ta_explicit* s = ta->add_state(init_state);
|
||||
assert(s == init_state);
|
||||
ta->add_to_initial_states_set(s);
|
||||
|
||||
todo.push(init_state);
|
||||
}
|
||||
todo.push(init_state);
|
||||
}
|
||||
tgba_init_state->destroy();
|
||||
|
||||
while (!todo.empty())
|
||||
{
|
||||
state_ta_explicit* source = todo.top();
|
||||
todo.pop();
|
||||
{
|
||||
state_ta_explicit* source = todo.top();
|
||||
todo.pop();
|
||||
|
||||
twa_succ_iterator* twa_succ_it =
|
||||
tgba_->succ_iter(source->get_tgba_state());
|
||||
for (twa_succ_it->first(); !twa_succ_it->done();
|
||||
twa_succ_it->next())
|
||||
{
|
||||
const state* tgba_state = twa_succ_it->dst();
|
||||
bdd tgba_condition = twa_succ_it->cond();
|
||||
acc_cond::mark_t tgba_acceptance_conditions =
|
||||
twa_succ_iterator* twa_succ_it =
|
||||
tgba_->succ_iter(source->get_tgba_state());
|
||||
for (twa_succ_it->first(); !twa_succ_it->done();
|
||||
twa_succ_it->next())
|
||||
{
|
||||
const state* tgba_state = twa_succ_it->dst();
|
||||
bdd tgba_condition = twa_succ_it->cond();
|
||||
acc_cond::mark_t tgba_acceptance_conditions =
|
||||
twa_succ_it->acc();
|
||||
bdd satone_tgba_condition;
|
||||
while ((satone_tgba_condition =
|
||||
bdd_satoneset(tgba_condition,
|
||||
atomic_propositions_set_, bddtrue))
|
||||
!= bddfalse)
|
||||
{
|
||||
tgba_condition -= satone_tgba_condition;
|
||||
bdd satone_tgba_condition;
|
||||
while ((satone_tgba_condition =
|
||||
bdd_satoneset(tgba_condition,
|
||||
atomic_propositions_set_, bddtrue))
|
||||
!= bddfalse)
|
||||
{
|
||||
tgba_condition -= satone_tgba_condition;
|
||||
|
||||
bdd all_props = bddtrue;
|
||||
bdd dest_condition;
|
||||
bdd all_props = bddtrue;
|
||||
bdd dest_condition;
|
||||
|
||||
bool is_acc = false;
|
||||
if (degeneralized)
|
||||
{
|
||||
twa_succ_iterator* it = tgba_->succ_iter(tgba_state);
|
||||
it->first();
|
||||
if (!it->done())
|
||||
is_acc = it->acc() != 0U;
|
||||
delete it;
|
||||
}
|
||||
bool is_acc = false;
|
||||
if (degeneralized)
|
||||
{
|
||||
twa_succ_iterator* it = tgba_->succ_iter(tgba_state);
|
||||
it->first();
|
||||
if (!it->done())
|
||||
is_acc = it->acc() != 0U;
|
||||
delete it;
|
||||
}
|
||||
|
||||
if (satone_tgba_condition == source->get_tgba_condition())
|
||||
while ((dest_condition =
|
||||
bdd_satoneset(all_props,
|
||||
atomic_propositions_set_, bddtrue))
|
||||
!= bddfalse)
|
||||
{
|
||||
all_props -= dest_condition;
|
||||
state_ta_explicit* new_dest =
|
||||
new state_ta_explicit(tgba_state->clone(),
|
||||
dest_condition, false, is_acc);
|
||||
state_ta_explicit* dest = ta->add_state(new_dest);
|
||||
if (satone_tgba_condition == source->get_tgba_condition())
|
||||
while ((dest_condition =
|
||||
bdd_satoneset(all_props,
|
||||
atomic_propositions_set_, bddtrue))
|
||||
!= bddfalse)
|
||||
{
|
||||
all_props -= dest_condition;
|
||||
state_ta_explicit* new_dest =
|
||||
new state_ta_explicit(tgba_state->clone(),
|
||||
dest_condition, false, is_acc);
|
||||
state_ta_explicit* dest = ta->add_state(new_dest);
|
||||
|
||||
if (dest != new_dest)
|
||||
{
|
||||
// the state dest already exists in the automaton
|
||||
new_dest->get_tgba_state()->destroy();
|
||||
delete new_dest;
|
||||
}
|
||||
else
|
||||
{
|
||||
todo.push(dest);
|
||||
}
|
||||
if (dest != new_dest)
|
||||
{
|
||||
// the state dest already exists in the automaton
|
||||
new_dest->get_tgba_state()->destroy();
|
||||
delete new_dest;
|
||||
}
|
||||
else
|
||||
{
|
||||
todo.push(dest);
|
||||
}
|
||||
|
||||
bdd cs = bdd_setxor(source->get_tgba_condition(),
|
||||
dest->get_tgba_condition());
|
||||
ta->create_transition(source, cs,
|
||||
tgba_acceptance_conditions, dest);
|
||||
}
|
||||
}
|
||||
tgba_state->destroy();
|
||||
}
|
||||
delete twa_succ_it;
|
||||
}
|
||||
bdd cs = bdd_setxor(source->get_tgba_condition(),
|
||||
dest->get_tgba_condition());
|
||||
ta->create_transition(source, cs,
|
||||
tgba_acceptance_conditions, dest);
|
||||
}
|
||||
}
|
||||
tgba_state->destroy();
|
||||
}
|
||||
delete twa_succ_it;
|
||||
}
|
||||
|
||||
if (no_livelock)
|
||||
return ta;
|
||||
return ta;
|
||||
|
||||
state_ta_explicit* artificial_livelock_acc_state = nullptr;
|
||||
|
||||
trace << "*** build_ta: artificial_livelock_acc_state_mode = ***"
|
||||
<< artificial_livelock_state_mode << std::endl;
|
||||
<< artificial_livelock_state_mode << std::endl;
|
||||
|
||||
if (artificial_livelock_state_mode)
|
||||
{
|
||||
single_pass_emptiness_check = true;
|
||||
artificial_livelock_acc_state =
|
||||
new state_ta_explicit(ta->get_tgba()->get_init_state(), bddtrue,
|
||||
false, false, true, nullptr);
|
||||
trace
|
||||
<< "*** build_ta: artificial_livelock_acc_state = ***"
|
||||
<< artificial_livelock_acc_state << std::endl;
|
||||
}
|
||||
{
|
||||
single_pass_emptiness_check = true;
|
||||
artificial_livelock_acc_state =
|
||||
new state_ta_explicit(ta->get_tgba()->get_init_state(), bddtrue,
|
||||
false, false, true, nullptr);
|
||||
trace
|
||||
<< "*** build_ta: artificial_livelock_acc_state = ***"
|
||||
<< artificial_livelock_acc_state << std::endl;
|
||||
}
|
||||
|
||||
compute_livelock_acceptance_states(ta, single_pass_emptiness_check,
|
||||
artificial_livelock_acc_state);
|
||||
artificial_livelock_acc_state);
|
||||
return ta;
|
||||
}
|
||||
}
|
||||
|
||||
ta_explicit_ptr
|
||||
tgba_to_ta(const const_twa_ptr& tgba_, bdd atomic_propositions_set_,
|
||||
bool degeneralized, bool artificial_initial_state_mode,
|
||||
bool single_pass_emptiness_check,
|
||||
bool artificial_livelock_state_mode,
|
||||
bool no_livelock)
|
||||
bool degeneralized, bool artificial_initial_state_mode,
|
||||
bool single_pass_emptiness_check,
|
||||
bool artificial_livelock_state_mode,
|
||||
bool no_livelock)
|
||||
{
|
||||
ta_explicit_ptr ta;
|
||||
|
||||
|
|
@ -555,10 +555,10 @@ namespace spot
|
|||
if (artificial_initial_state_mode)
|
||||
{
|
||||
state_ta_explicit* artificial_init_state =
|
||||
new state_ta_explicit(tgba_init_state->clone(), bddfalse, true);
|
||||
new state_ta_explicit(tgba_init_state->clone(), bddfalse, true);
|
||||
|
||||
ta = make_ta_explicit(tgba_, tgba_->acc().num_sets(),
|
||||
artificial_init_state);
|
||||
artificial_init_state);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -568,8 +568,8 @@ namespace spot
|
|||
|
||||
// build ta automaton
|
||||
build_ta(ta, atomic_propositions_set_, degeneralized,
|
||||
single_pass_emptiness_check, artificial_livelock_state_mode,
|
||||
no_livelock);
|
||||
single_pass_emptiness_check, artificial_livelock_state_mode,
|
||||
no_livelock);
|
||||
|
||||
// (degeneralized=true) => TA
|
||||
if (degeneralized)
|
||||
|
|
@ -589,8 +589,8 @@ namespace spot
|
|||
state_ta_explicit::transitions::iterator it_trans;
|
||||
|
||||
for (it_trans = trans->begin(); it_trans != trans->end();
|
||||
++it_trans)
|
||||
(*it_trans)->acceptance_conditions = ta->acc().all_sets();
|
||||
++it_trans)
|
||||
(*it_trans)->acceptance_conditions = ta->acc().all_sets();
|
||||
|
||||
state->set_accepting_state(false);
|
||||
}
|
||||
|
|
@ -604,11 +604,11 @@ namespace spot
|
|||
{
|
||||
auto tgba_init_state = tgba_->get_init_state();
|
||||
auto artificial_init_state = new state_ta_explicit(tgba_init_state->clone(),
|
||||
bddfalse, true);
|
||||
bddfalse, true);
|
||||
tgba_init_state->destroy();
|
||||
|
||||
auto tgta = make_tgta_explicit(tgba_, tgba_->acc().num_sets(),
|
||||
artificial_init_state);
|
||||
artificial_init_state);
|
||||
|
||||
// build a Generalized TA automaton involving a single_pass_emptiness_check
|
||||
// (without an artificial livelock state):
|
||||
|
|
@ -625,14 +625,14 @@ namespace spot
|
|||
initial_states_iter->first();
|
||||
if (initial_states_iter->done())
|
||||
{
|
||||
delete initial_states_iter;
|
||||
return tgta;
|
||||
delete initial_states_iter;
|
||||
return tgta;
|
||||
}
|
||||
bdd first_state_condition = initial_states_iter->cond();
|
||||
delete initial_states_iter;
|
||||
|
||||
bdd bdd_stutering_transition = bdd_setxor(first_state_condition,
|
||||
first_state_condition);
|
||||
first_state_condition);
|
||||
|
||||
for (it = states_set.begin(); it != states_set.end(); ++it)
|
||||
{
|
||||
|
|
@ -645,13 +645,13 @@ namespace spot
|
|||
if (trans_empty || state->is_accepting_state())
|
||||
{
|
||||
ta->create_transition(state, bdd_stutering_transition,
|
||||
ta->acc().all_sets(), state);
|
||||
ta->acc().all_sets(), state);
|
||||
}
|
||||
}
|
||||
|
||||
if (state->compare(ta->get_artificial_initial_state()))
|
||||
ta->create_transition(state, bdd_stutering_transition,
|
||||
0U, state);
|
||||
0U, state);
|
||||
|
||||
state->set_livelock_accepting_state(false);
|
||||
state->set_accepting_state(false);
|
||||
|
|
|
|||
|
|
@ -83,11 +83,11 @@ namespace spot
|
|||
/// TGBA \a tgba_to_convert.
|
||||
SPOT_API ta_explicit_ptr
|
||||
tgba_to_ta(const const_twa_ptr& tgba_to_convert, bdd atomic_propositions_set,
|
||||
bool degeneralized = true,
|
||||
bool artificial_initial_state_mode = true,
|
||||
bool single_pass_emptiness_check = false,
|
||||
bool artificial_livelock_state_mode = false,
|
||||
bool no_livelock = false);
|
||||
bool degeneralized = true,
|
||||
bool artificial_initial_state_mode = true,
|
||||
bool single_pass_emptiness_check = false,
|
||||
bool artificial_livelock_state_mode = false,
|
||||
bool no_livelock = false);
|
||||
|
||||
/// \ingroup tgba_ta
|
||||
/// \brief Build a spot::tgta_explicit* (TGTA) from an LTL formula.
|
||||
|
|
@ -100,5 +100,5 @@ namespace spot
|
|||
/// language as the TGBA \a tgba_to_convert.
|
||||
SPOT_API tgta_explicit_ptr
|
||||
tgba_to_tgta(const const_twa_ptr& tgba_to_convert,
|
||||
bdd atomic_propositions_set);
|
||||
bdd atomic_propositions_set);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ namespace spot
|
|||
atomic_prop_set res;
|
||||
for (unsigned i = 0; i < n; ++i)
|
||||
{
|
||||
std::ostringstream p;
|
||||
p << 'p' << i;
|
||||
res.insert(formula::ap(p.str()));
|
||||
std::ostringstream p;
|
||||
p << 'p' << i;
|
||||
res.insert(formula::ap(p.str()));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -44,11 +44,11 @@ namespace spot
|
|||
if (!s)
|
||||
s = new atomic_prop_set;
|
||||
f.traverse([&](const formula& f)
|
||||
{
|
||||
if (f.is(op::ap))
|
||||
s->insert(f);
|
||||
return false;
|
||||
});
|
||||
{
|
||||
if (f.is(op::ap))
|
||||
s->insert(f);
|
||||
return false;
|
||||
});
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ namespace spot
|
|||
// Check whether L(l) is a subset of L(g).
|
||||
bool
|
||||
language_containment_checker::contained(formula l,
|
||||
formula g)
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return true;
|
||||
|
|
@ -77,7 +77,7 @@ namespace spot
|
|||
// Check whether L(!l) is a subset of L(g).
|
||||
bool
|
||||
language_containment_checker::neg_contained(formula l,
|
||||
formula g)
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return false;
|
||||
|
|
@ -92,7 +92,7 @@ namespace spot
|
|||
// Check whether L(l) is a subset of L(!g).
|
||||
bool
|
||||
language_containment_checker::contained_neg(formula l,
|
||||
formula g)
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return false;
|
||||
|
|
@ -122,7 +122,7 @@ namespace spot
|
|||
return &i->second;
|
||||
|
||||
auto e = ltl_to_tgba_fm(f, dict_, exprop_, symb_merge_,
|
||||
branching_postponement_, fair_loop_approx_);
|
||||
branching_postponement_, fair_loop_approx_);
|
||||
record_& r = translated_[f];
|
||||
r.translation = e;
|
||||
return &r;
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ namespace spot
|
|||
/// This class uses spot::ltl_to_tgba_fm to translate LTL
|
||||
/// formulae. See that function for the meaning of these options.
|
||||
language_containment_checker(const bdd_dict_ptr& dict, bool exprop,
|
||||
bool symb_merge,
|
||||
bool branching_postponement,
|
||||
bool fair_loop_approx);
|
||||
bool symb_merge,
|
||||
bool branching_postponement,
|
||||
bool fair_loop_approx);
|
||||
|
||||
~language_containment_checker();
|
||||
|
||||
|
|
|
|||
156
spot/tl/dot.cc
156
spot/tl/dot.cc
|
|
@ -37,94 +37,94 @@ namespace spot
|
|||
std::ostringstream* sinks_;
|
||||
|
||||
dot_printer(std::ostream& os, formula f)
|
||||
: os_(os), sinks_(new std::ostringstream)
|
||||
{
|
||||
os_ << "digraph G {\n";
|
||||
rec(f);
|
||||
os_ << " subgraph atoms {\n rank=sink;\n"
|
||||
<< sinks_->str() << " }\n}\n";
|
||||
}
|
||||
: os_(os), sinks_(new std::ostringstream)
|
||||
{
|
||||
os_ << "digraph G {\n";
|
||||
rec(f);
|
||||
os_ << " subgraph atoms {\n rank=sink;\n"
|
||||
<< sinks_->str() << " }\n}\n";
|
||||
}
|
||||
|
||||
~dot_printer()
|
||||
{
|
||||
delete sinks_;
|
||||
}
|
||||
{
|
||||
delete sinks_;
|
||||
}
|
||||
|
||||
int rec(formula f)
|
||||
{
|
||||
auto i = node_.emplace(f, node_.size());
|
||||
int src = i.first->second;
|
||||
if (!i.second)
|
||||
return src;
|
||||
auto i = node_.emplace(f, node_.size());
|
||||
int src = i.first->second;
|
||||
if (!i.second)
|
||||
return src;
|
||||
|
||||
op o = f.kind();
|
||||
std::string str = (o == op::ap) ? f.ap_name() : f.kindstr();
|
||||
op o = f.kind();
|
||||
std::string str = (o == op::ap) ? f.ap_name() : f.kindstr();
|
||||
|
||||
if (o == op::ap || f.is_constant())
|
||||
*sinks_ << " " << src << " [label=\""
|
||||
<< str << "\", shape=box];\n";
|
||||
else
|
||||
os_ << " " << src << " [label=\"" << str << "\"];\n";
|
||||
if (o == op::ap || f.is_constant())
|
||||
*sinks_ << " " << src << " [label=\""
|
||||
<< str << "\", shape=box];\n";
|
||||
else
|
||||
os_ << " " << src << " [label=\"" << str << "\"];\n";
|
||||
|
||||
int childnum = 0;
|
||||
switch (o)
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
childnum = 0; // No number for children
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
childnum = -2; // L and R markers
|
||||
break;
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
childnum = 1; // Numbered children
|
||||
break;
|
||||
}
|
||||
int childnum = 0;
|
||||
switch (o)
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
childnum = 0; // No number for children
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
childnum = -2; // L and R markers
|
||||
break;
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
childnum = 1; // Numbered children
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto c: f)
|
||||
{
|
||||
// Do not merge the next two lines, as there is no
|
||||
// guarantee that rec will be called before we start
|
||||
// printing the transition.
|
||||
int dst = rec(c);
|
||||
os_ << " " << src << " -> " << dst;
|
||||
if (childnum > 0)
|
||||
os_ << " [taillabel=\"" << childnum << "\"]";
|
||||
if (childnum == -2)
|
||||
os_ << " [taillabel=\"L\"]";
|
||||
else if (childnum == -1)
|
||||
os_ << " [taillabel=\"R\"]";
|
||||
os_ << ";\n";
|
||||
++childnum;
|
||||
}
|
||||
for (auto c: f)
|
||||
{
|
||||
// Do not merge the next two lines, as there is no
|
||||
// guarantee that rec will be called before we start
|
||||
// printing the transition.
|
||||
int dst = rec(c);
|
||||
os_ << " " << src << " -> " << dst;
|
||||
if (childnum > 0)
|
||||
os_ << " [taillabel=\"" << childnum << "\"]";
|
||||
if (childnum == -2)
|
||||
os_ << " [taillabel=\"L\"]";
|
||||
else if (childnum == -1)
|
||||
os_ << " [taillabel=\"R\"]";
|
||||
os_ << ";\n";
|
||||
++childnum;
|
||||
}
|
||||
|
||||
return src;
|
||||
return src;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,66 +33,66 @@ namespace spot
|
|||
std::vector<formula> group;
|
||||
auto start = arg;
|
||||
while (*start)
|
||||
{
|
||||
while (*start == ' ' || *start == '\t')
|
||||
++start;
|
||||
if (!*start)
|
||||
break;
|
||||
if (*start == ',')
|
||||
{
|
||||
std::string s = "unexpected ',' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
if (*start == '"')
|
||||
{
|
||||
++start;
|
||||
auto end = start;
|
||||
while (*end && *end != '"')
|
||||
{
|
||||
if (*end == '\\')
|
||||
++end;
|
||||
++end;
|
||||
}
|
||||
if (!*end)
|
||||
{
|
||||
std::string s = "missing closing '\"' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
std::string ap(start, end - start);
|
||||
group.emplace_back(formula::ap(ap));
|
||||
do
|
||||
++end;
|
||||
while (*end == ' ' || *end == '\t');
|
||||
if (*end && *end != ',')
|
||||
{
|
||||
std::string s = "unexpected character '";
|
||||
s += *end;
|
||||
s += "' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
if (*end == ',')
|
||||
++end;
|
||||
start = end;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto end = start;
|
||||
while (*end && *end != ',')
|
||||
++end;
|
||||
auto rend = end;
|
||||
while (rend > start && (rend[-1] == ' ' || rend[-1] == '\t'))
|
||||
--rend;
|
||||
std::string ap(start, rend - start);
|
||||
group.emplace_back(formula::ap(ap));
|
||||
if (*end == ',')
|
||||
start = end + 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
while (*start == ' ' || *start == '\t')
|
||||
++start;
|
||||
if (!*start)
|
||||
break;
|
||||
if (*start == ',')
|
||||
{
|
||||
std::string s = "unexpected ',' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
if (*start == '"')
|
||||
{
|
||||
++start;
|
||||
auto end = start;
|
||||
while (*end && *end != '"')
|
||||
{
|
||||
if (*end == '\\')
|
||||
++end;
|
||||
++end;
|
||||
}
|
||||
if (!*end)
|
||||
{
|
||||
std::string s = "missing closing '\"' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
std::string ap(start, end - start);
|
||||
group.emplace_back(formula::ap(ap));
|
||||
do
|
||||
++end;
|
||||
while (*end == ' ' || *end == '\t');
|
||||
if (*end && *end != ',')
|
||||
{
|
||||
std::string s = "unexpected character '";
|
||||
s += *end;
|
||||
s += "' in ";
|
||||
s += arg;
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
if (*end == ',')
|
||||
++end;
|
||||
start = end;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto end = start;
|
||||
while (*end && *end != ',')
|
||||
++end;
|
||||
auto rend = end;
|
||||
while (rend > start && (rend[-1] == ' ' || rend[-1] == '\t'))
|
||||
--rend;
|
||||
std::string ap(start, rend - start);
|
||||
group.emplace_back(formula::ap(ap));
|
||||
if (*end == ',')
|
||||
start = end + 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
|
@ -126,16 +126,16 @@ namespace spot
|
|||
|
||||
for (auto& g: groups)
|
||||
{
|
||||
group.clear();
|
||||
group.clear();
|
||||
|
||||
for (auto ap: g)
|
||||
if (s->find(ap) != s->end())
|
||||
group.push_back(ap);
|
||||
for (auto ap: g)
|
||||
if (s->find(ap) != s->end())
|
||||
group.push_back(ap);
|
||||
|
||||
unsigned s = group.size();
|
||||
for (unsigned j = 0; j < s; ++j)
|
||||
for (unsigned k = j + 1; k < s; ++k)
|
||||
v.push_back(nand(group[j], group[k]));
|
||||
unsigned s = group.size();
|
||||
for (unsigned j = 0; j < s; ++j)
|
||||
for (unsigned k = j + 1; k < s; ++k)
|
||||
v.push_back(nand(group[j], group[k]));
|
||||
};
|
||||
|
||||
delete s;
|
||||
|
|
@ -143,15 +143,15 @@ namespace spot
|
|||
}
|
||||
|
||||
twa_graph_ptr exclusive_ap::constrain(const_twa_graph_ptr aut,
|
||||
bool simplify_guards) const
|
||||
bool simplify_guards) const
|
||||
{
|
||||
// Compute the support of the automaton.
|
||||
bdd support = bddtrue;
|
||||
{
|
||||
std::set<int> bdd_seen;
|
||||
for (auto& t: aut->edges())
|
||||
if (bdd_seen.insert(t.cond.id()).second)
|
||||
support &= bdd_support(t.cond);
|
||||
if (bdd_seen.insert(t.cond.id()).second)
|
||||
support &= bdd_support(t.cond);
|
||||
}
|
||||
|
||||
bdd restrict = bddtrue;
|
||||
|
|
@ -160,19 +160,19 @@ namespace spot
|
|||
std::vector<bdd> group;
|
||||
for (auto& g: groups)
|
||||
{
|
||||
group.clear();
|
||||
group.clear();
|
||||
|
||||
for (auto ap: g)
|
||||
{
|
||||
int v = d->has_registered_proposition(ap, aut);
|
||||
if (v >= 0)
|
||||
group.push_back(bdd_nithvar(v));
|
||||
}
|
||||
for (auto ap: g)
|
||||
{
|
||||
int v = d->has_registered_proposition(ap, aut);
|
||||
if (v >= 0)
|
||||
group.push_back(bdd_nithvar(v));
|
||||
}
|
||||
|
||||
unsigned s = group.size();
|
||||
for (unsigned j = 0; j < s; ++j)
|
||||
for (unsigned k = j + 1; k < s; ++k)
|
||||
restrict &= group[j] | group[k];
|
||||
unsigned s = group.size();
|
||||
for (unsigned j = 0; j < s; ++j)
|
||||
for (unsigned k = j + 1; k < s; ++k)
|
||||
restrict &= group[j] | group[k];
|
||||
}
|
||||
|
||||
twa_graph_ptr res = make_twa_graph(aut->get_dict());
|
||||
|
|
@ -181,26 +181,26 @@ namespace spot
|
|||
res->copy_acceptance_of(aut);
|
||||
if (simplify_guards)
|
||||
{
|
||||
transform_accessible(aut, res, [&](unsigned, bdd& cond,
|
||||
acc_cond::mark_t&, unsigned)
|
||||
{
|
||||
minato_isop isop(cond & restrict,
|
||||
cond | !restrict,
|
||||
true);
|
||||
bdd res = bddfalse;
|
||||
bdd cube = bddfalse;
|
||||
while ((cube = isop.next()) != bddfalse)
|
||||
res |= cube;
|
||||
cond = res;
|
||||
});
|
||||
transform_accessible(aut, res, [&](unsigned, bdd& cond,
|
||||
acc_cond::mark_t&, unsigned)
|
||||
{
|
||||
minato_isop isop(cond & restrict,
|
||||
cond | !restrict,
|
||||
true);
|
||||
bdd res = bddfalse;
|
||||
bdd cube = bddfalse;
|
||||
while ((cube = isop.next()) != bddfalse)
|
||||
res |= cube;
|
||||
cond = res;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
transform_accessible(aut, res, [&](unsigned, bdd& cond,
|
||||
acc_cond::mark_t&, unsigned)
|
||||
{
|
||||
cond &= restrict;
|
||||
});
|
||||
transform_accessible(aut, res, [&](unsigned, bdd& cond,
|
||||
acc_cond::mark_t&, unsigned)
|
||||
{
|
||||
cond &= restrict;
|
||||
});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,6 @@ namespace spot
|
|||
|
||||
formula constrain(formula f) const;
|
||||
twa_graph_ptr constrain(const_twa_graph_ptr aut,
|
||||
bool simplify_guards = false) const;
|
||||
bool simplify_guards = false) const;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
2524
spot/tl/formula.cc
2524
spot/tl/formula.cc
File diff suppressed because it is too large
Load diff
1292
spot/tl/formula.hh
1292
spot/tl/formula.hh
File diff suppressed because it is too large
Load diff
|
|
@ -30,14 +30,14 @@ namespace spot
|
|||
{
|
||||
int len = 0;
|
||||
f.traverse([&len](const formula& x)
|
||||
{
|
||||
auto s = x.size();
|
||||
if (s > 1)
|
||||
len += s - 1;
|
||||
else
|
||||
++len;
|
||||
return false;
|
||||
});
|
||||
{
|
||||
auto s = x.size();
|
||||
if (s > 1)
|
||||
len += s - 1;
|
||||
else
|
||||
++len;
|
||||
return false;
|
||||
});
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
@ -46,31 +46,31 @@ namespace spot
|
|||
{
|
||||
int len = 0;
|
||||
f.traverse([&len](const formula& x)
|
||||
{
|
||||
if (x.is_boolean())
|
||||
{
|
||||
++len;
|
||||
return true;
|
||||
}
|
||||
auto s = x.size();
|
||||
if (s > 2)
|
||||
{
|
||||
int b = 0;
|
||||
for (const auto& y: x)
|
||||
if (y.is_boolean())
|
||||
++b;
|
||||
len += s - b * 2 + 1;
|
||||
}
|
||||
else if (s > 1)
|
||||
{
|
||||
len += s - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++len;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
{
|
||||
if (x.is_boolean())
|
||||
{
|
||||
++len;
|
||||
return true;
|
||||
}
|
||||
auto s = x.size();
|
||||
if (s > 2)
|
||||
{
|
||||
int b = 0;
|
||||
for (const auto& y: x)
|
||||
if (y.is_boolean())
|
||||
++b;
|
||||
len += s - b * 2 + 1;
|
||||
}
|
||||
else if (s > 1)
|
||||
{
|
||||
len += s - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++len;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
|
|||
126
spot/tl/mark.cc
126
spot/tl/mark.cc
|
|
@ -58,25 +58,25 @@ namespace spot
|
|||
case op::UConcat:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
res = f;
|
||||
break;
|
||||
res = f;
|
||||
break;
|
||||
case op::NegClosure:
|
||||
res = formula::NegClosureMarked(f[0]);
|
||||
break;
|
||||
res = formula::NegClosureMarked(f[0]);
|
||||
break;
|
||||
case op::EConcat:
|
||||
res = formula::EConcatMarked(f[0], f[1]);
|
||||
break;
|
||||
res = formula::EConcatMarked(f[0], f[1]);
|
||||
break;
|
||||
case op::Or:
|
||||
case op::And:
|
||||
res = f.map([this](formula f)
|
||||
{
|
||||
return this->mark_concat_ops(f);
|
||||
});
|
||||
break;
|
||||
res = f.map([this](formula f)
|
||||
{
|
||||
return this->mark_concat_ops(f);
|
||||
});
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
SPOT_UNIMPLEMENTED();
|
||||
SPOT_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
markops_[f] = res;
|
||||
|
|
@ -95,7 +95,7 @@ namespace spot
|
|||
|
||||
auto recurse = [this](formula f)
|
||||
{
|
||||
return this->simplify_mark(f);
|
||||
return this->simplify_mark(f);
|
||||
};
|
||||
|
||||
formula res;
|
||||
|
|
@ -119,58 +119,58 @@ namespace spot
|
|||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
res = f;
|
||||
break;
|
||||
res = f;
|
||||
break;
|
||||
case op::Or:
|
||||
res = f.map(recurse);
|
||||
break;
|
||||
res = f.map(recurse);
|
||||
break;
|
||||
case op::And:
|
||||
{
|
||||
std::set<std::pair<formula, formula>> empairs;
|
||||
std::set<formula> nmset;
|
||||
std::vector<formula> elist;
|
||||
std::vector<formula> nlist;
|
||||
std::vector<formula> v;
|
||||
{
|
||||
std::set<std::pair<formula, formula>> empairs;
|
||||
std::set<formula> nmset;
|
||||
std::vector<formula> elist;
|
||||
std::vector<formula> nlist;
|
||||
std::vector<formula> v;
|
||||
|
||||
for (auto c: f)
|
||||
{
|
||||
if (c.is(op::EConcatMarked))
|
||||
{
|
||||
empairs.emplace(c[0], c[1]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::EConcat))
|
||||
{
|
||||
elist.push_back(c);
|
||||
}
|
||||
else if (c.is(op::NegClosureMarked))
|
||||
{
|
||||
nmset.insert(c[0]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::NegClosure))
|
||||
{
|
||||
nlist.push_back(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.push_back(c);
|
||||
}
|
||||
}
|
||||
// Keep only the non-marked EConcat for which we
|
||||
// have not seen a similar EConcatMarked.
|
||||
for (auto e: elist)
|
||||
if (empairs.find(std::make_pair(e[0], e[1]))
|
||||
== empairs.end())
|
||||
v.push_back(e);
|
||||
// Keep only the non-marked NegClosure for which we
|
||||
// have not seen a similar NegClosureMarked.
|
||||
for (auto n: nlist)
|
||||
if (nmset.find(n[0]) == nmset.end())
|
||||
v.push_back(n);
|
||||
res = formula::And(v);
|
||||
}
|
||||
break;
|
||||
for (auto c: f)
|
||||
{
|
||||
if (c.is(op::EConcatMarked))
|
||||
{
|
||||
empairs.emplace(c[0], c[1]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::EConcat))
|
||||
{
|
||||
elist.push_back(c);
|
||||
}
|
||||
else if (c.is(op::NegClosureMarked))
|
||||
{
|
||||
nmset.insert(c[0]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::NegClosure))
|
||||
{
|
||||
nlist.push_back(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.push_back(c);
|
||||
}
|
||||
}
|
||||
// Keep only the non-marked EConcat for which we
|
||||
// have not seen a similar EConcatMarked.
|
||||
for (auto e: elist)
|
||||
if (empairs.find(std::make_pair(e[0], e[1]))
|
||||
== empairs.end())
|
||||
v.push_back(e);
|
||||
// Keep only the non-marked NegClosure for which we
|
||||
// have not seen a similar NegClosureMarked.
|
||||
for (auto n: nlist)
|
||||
if (nmset.find(n[0]) == nmset.end())
|
||||
v.push_back(n);
|
||||
res = formula::And(v);
|
||||
}
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
|
|
@ -181,7 +181,7 @@ namespace spot
|
|||
case op::FStar:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
SPOT_UNIMPLEMENTED();
|
||||
SPOT_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
simpmark_[f] = res;
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@ namespace spot
|
|||
formula substitute_ap(formula f, formula ap_src, formula ap_dst)
|
||||
{
|
||||
return f.map([&](formula f)
|
||||
{
|
||||
if (f == ap_src)
|
||||
return ap_dst;
|
||||
else
|
||||
return substitute_ap(f, ap_src, ap_dst);
|
||||
});
|
||||
{
|
||||
if (f == ap_src)
|
||||
return ap_dst;
|
||||
else
|
||||
return substitute_ap(f, ap_src, ap_dst);
|
||||
});
|
||||
}
|
||||
|
||||
typedef std::vector<formula> vec;
|
||||
|
|
@ -58,229 +58,229 @@ namespace spot
|
|||
|
||||
formula mutate(formula f)
|
||||
{
|
||||
auto recurse = [this](formula f)
|
||||
{
|
||||
return this->mutate(f);
|
||||
};
|
||||
auto recurse = [this](formula f)
|
||||
{
|
||||
return this->mutate(f);
|
||||
};
|
||||
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
return f;
|
||||
case op::ap:
|
||||
if (opts_ & Mut_Ap2Const)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::tt();
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::ff();
|
||||
}
|
||||
return f;
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
if ((opts_ & Mut_Remove_Ops)
|
||||
&& mutation_counter_-- == 0)
|
||||
return f[0];
|
||||
// fall through
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
{
|
||||
int mos = f.size();
|
||||
if (opts_ & Mut_Remove_Multop_Operands)
|
||||
{
|
||||
for (int i = 0; i < mos; ++i)
|
||||
if (mutation_counter_-- == 0)
|
||||
return f.all_but(i);
|
||||
}
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
return f;
|
||||
case op::ap:
|
||||
if (opts_ & Mut_Ap2Const)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::tt();
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::ff();
|
||||
}
|
||||
return f;
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
if ((opts_ & Mut_Remove_Ops)
|
||||
&& mutation_counter_-- == 0)
|
||||
return f[0];
|
||||
// fall through
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
{
|
||||
int mos = f.size();
|
||||
if (opts_ & Mut_Remove_Multop_Operands)
|
||||
{
|
||||
for (int i = 0; i < mos; ++i)
|
||||
if (mutation_counter_-- == 0)
|
||||
return f.all_but(i);
|
||||
}
|
||||
|
||||
if (opts_ & Mut_Split_Ops && f.is(op::AndNLM))
|
||||
{
|
||||
if (mutation_counter_ >= 0
|
||||
&& mutation_counter_ < 2 * (mos - 1))
|
||||
{
|
||||
vec v1;
|
||||
vec v2;
|
||||
v1.push_back(f[0]);
|
||||
bool reverse = false;
|
||||
int i = 1;
|
||||
while (i < mos)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
break;
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
reverse = true;
|
||||
break;
|
||||
}
|
||||
v1.push_back(f[i++]);
|
||||
}
|
||||
for (; i < mos; ++i)
|
||||
v2.push_back(f[i]);
|
||||
formula first = AndNLM_(v1);
|
||||
formula second = AndNLM_(v2);
|
||||
formula ost = formula::one_star();
|
||||
if (!reverse)
|
||||
return AndRat_(Concat_(first, ost), second);
|
||||
else
|
||||
return AndRat_(Concat_(second, ost), first);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutation_counter_ -= 2 * (mos - 1);
|
||||
}
|
||||
}
|
||||
if (opts_ & Mut_Split_Ops && f.is(op::AndNLM))
|
||||
{
|
||||
if (mutation_counter_ >= 0
|
||||
&& mutation_counter_ < 2 * (mos - 1))
|
||||
{
|
||||
vec v1;
|
||||
vec v2;
|
||||
v1.push_back(f[0]);
|
||||
bool reverse = false;
|
||||
int i = 1;
|
||||
while (i < mos)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
break;
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
reverse = true;
|
||||
break;
|
||||
}
|
||||
v1.push_back(f[i++]);
|
||||
}
|
||||
for (; i < mos; ++i)
|
||||
v2.push_back(f[i]);
|
||||
formula first = AndNLM_(v1);
|
||||
formula second = AndNLM_(v2);
|
||||
formula ost = formula::one_star();
|
||||
if (!reverse)
|
||||
return AndRat_(Concat_(first, ost), second);
|
||||
else
|
||||
return AndRat_(Concat_(second, ost), first);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutation_counter_ -= 2 * (mos - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
{
|
||||
formula first = f[0];
|
||||
formula second = f[1];
|
||||
op o = f.kind();
|
||||
bool left_is_sere = o == op::EConcat
|
||||
|| o == op::EConcatMarked
|
||||
|| o == op::UConcat;
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
{
|
||||
formula first = f[0];
|
||||
formula second = f[1];
|
||||
op o = f.kind();
|
||||
bool left_is_sere = o == op::EConcat
|
||||
|| o == op::EConcatMarked
|
||||
|| o == op::UConcat;
|
||||
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
{
|
||||
if (!left_is_sere)
|
||||
return first;
|
||||
else if (o == op::UConcat)
|
||||
return formula::NegClosure(first);
|
||||
else // EConcat or EConcatMarked
|
||||
return formula::Closure(first);
|
||||
}
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return second;
|
||||
if (opts_ & Mut_Rewrite_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::U:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(first, second);
|
||||
break;
|
||||
case op::M:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::R(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::U(second, first);
|
||||
break;
|
||||
case op::R:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(second, first);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opts_ & Mut_Split_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::Equiv:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(second, first);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, second});
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
// Negate the two argument sequentially (in this
|
||||
// case right before left, otherwise different
|
||||
// compilers will make different choices.
|
||||
auto right = formula::Not(second);
|
||||
return formula::And({formula::Not(first), right});
|
||||
}
|
||||
break;
|
||||
case op::Xor:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, formula::Not(second)});
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({formula::Not(first), second});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
{
|
||||
formula c = f[0];
|
||||
op o = f.kind();
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return c;
|
||||
if (opts_ & Mut_Simplify_Bounds)
|
||||
{
|
||||
auto min = f.min();
|
||||
auto max = f.max();
|
||||
if (min > 0)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min - 1, max);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, 0, max);
|
||||
}
|
||||
if (max != formula::unbounded())
|
||||
{
|
||||
if (max > min && mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min, max - 1);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min,
|
||||
formula::unbounded());
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
{
|
||||
if (!left_is_sere)
|
||||
return first;
|
||||
else if (o == op::UConcat)
|
||||
return formula::NegClosure(first);
|
||||
else // EConcat or EConcatMarked
|
||||
return formula::Closure(first);
|
||||
}
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return second;
|
||||
if (opts_ & Mut_Rewrite_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::U:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(first, second);
|
||||
break;
|
||||
case op::M:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::R(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::U(second, first);
|
||||
break;
|
||||
case op::R:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(second, first);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opts_ & Mut_Split_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::Equiv:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(second, first);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, second});
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
// Negate the two argument sequentially (in this
|
||||
// case right before left, otherwise different
|
||||
// compilers will make different choices.
|
||||
auto right = formula::Not(second);
|
||||
return formula::And({formula::Not(first), right});
|
||||
}
|
||||
break;
|
||||
case op::Xor:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, formula::Not(second)});
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({formula::Not(first), second});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
{
|
||||
formula c = f[0];
|
||||
op o = f.kind();
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return c;
|
||||
if (opts_ & Mut_Simplify_Bounds)
|
||||
{
|
||||
auto min = f.min();
|
||||
auto max = f.max();
|
||||
if (min > 0)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min - 1, max);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, 0, max);
|
||||
}
|
||||
if (max != formula::unbounded())
|
||||
{
|
||||
if (max > min && mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min, max - 1);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min,
|
||||
formula::unbounded());
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
|
||||
formula
|
||||
get_mutation(int n)
|
||||
{
|
||||
mutation_counter_ = n;
|
||||
formula mut = mutate(f_);
|
||||
if (mut == f_)
|
||||
return nullptr;
|
||||
return mut;
|
||||
mutation_counter_ = n;
|
||||
formula mut = mutate(f_);
|
||||
if (mut == f_)
|
||||
return nullptr;
|
||||
return mut;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -291,13 +291,13 @@ namespace spot
|
|||
assert(left != nullptr);
|
||||
assert(right != nullptr);
|
||||
if (left == right)
|
||||
return false;
|
||||
return false;
|
||||
auto ll = length(left);
|
||||
auto lr = length(right);
|
||||
if (ll < lr)
|
||||
return true;
|
||||
return true;
|
||||
if (ll > lr)
|
||||
return false;
|
||||
return false;
|
||||
return left < right;
|
||||
}
|
||||
|
||||
|
|
@ -305,55 +305,55 @@ namespace spot
|
|||
|
||||
void
|
||||
single_mutation_rec(formula f, fset_t& mutations, unsigned opts,
|
||||
unsigned& n, unsigned m)
|
||||
unsigned& n, unsigned m)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
else
|
||||
{
|
||||
formula mut;
|
||||
int i = 0;
|
||||
mutator mv(f, opts);
|
||||
while (n > 0 && ((mut = mv.get_mutation(i++)) != nullptr))
|
||||
single_mutation_rec(mut, mutations, opts, n, m - 1);
|
||||
}
|
||||
{
|
||||
formula mut;
|
||||
int i = 0;
|
||||
mutator mv(f, opts);
|
||||
while (n > 0 && ((mut = mv.get_mutation(i++)) != nullptr))
|
||||
single_mutation_rec(mut, mutations, opts, n, m - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
replace_ap_rec(formula f, fset_t& mutations, unsigned opts,
|
||||
unsigned& n, unsigned m)
|
||||
unsigned& n, unsigned m)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!n)
|
||||
return;
|
||||
auto aps =
|
||||
std::unique_ptr<atomic_prop_set>(atomic_prop_collect(f));
|
||||
for (auto ap1: *aps)
|
||||
for (auto ap2: *aps)
|
||||
{
|
||||
if (ap1 == ap2)
|
||||
continue;
|
||||
auto mut = substitute_ap(f, ap1, ap2);
|
||||
replace_ap_rec(mut, mutations, opts, n, m - 1);
|
||||
if (!n)
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (!n)
|
||||
return;
|
||||
auto aps =
|
||||
std::unique_ptr<atomic_prop_set>(atomic_prop_collect(f));
|
||||
for (auto ap1: *aps)
|
||||
for (auto ap2: *aps)
|
||||
{
|
||||
if (ap1 == ap2)
|
||||
continue;
|
||||
auto mut = substitute_ap(f, ap1, ap2);
|
||||
replace_ap_rec(mut, mutations, opts, n, m - 1);
|
||||
if (!n)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<formula>
|
||||
mutate(formula f, unsigned opts, unsigned max_output,
|
||||
unsigned mutation_count, bool sort)
|
||||
unsigned mutation_count, bool sort)
|
||||
{
|
||||
fset_t mutations;
|
||||
single_mutation_rec(f, mutations, opts, max_output, mutation_count);
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ namespace spot
|
|||
|
||||
SPOT_API
|
||||
std::vector<formula> mutate(formula f,
|
||||
unsigned opts = Mut_All,
|
||||
unsigned max_output = -1U,
|
||||
unsigned mutation_count = 1,
|
||||
bool sort = true);
|
||||
unsigned opts = Mut_All,
|
||||
unsigned max_output = -1U,
|
||||
unsigned mutation_count = 1,
|
||||
bool sort = true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,8 +94,8 @@ namespace spot
|
|||
/// \param shift how many characters to add to the error locations
|
||||
/// \return \c true iff any diagnostic was output.
|
||||
bool format_errors(std::ostream& os,
|
||||
const std::string& input,
|
||||
unsigned shift);
|
||||
const std::string& input,
|
||||
unsigned shift);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -119,10 +119,10 @@ namespace spot
|
|||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
parsed_formula parse_infix_psl(const std::string& ltl_string,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
|
||||
/// \brief Build a Boolean formula from a string.
|
||||
/// \param ltl_string The string to parse.
|
||||
|
|
@ -142,10 +142,10 @@ namespace spot
|
|||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
parsed_formula parse_infix_boolean(const std::string& ltl_string,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
|
||||
/// \brief Build a formula from an LTL string in LBT's format.
|
||||
/// \param ltl_string The string to parse.
|
||||
|
|
@ -167,9 +167,9 @@ namespace spot
|
|||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
parsed_formula parse_prefix_ltl(const std::string& ltl_string,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false);
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false);
|
||||
|
||||
/// \brief A simple wrapper to parse_infix_psl() and parse_prefix_ltl().
|
||||
///
|
||||
|
|
@ -179,7 +179,7 @@ namespace spot
|
|||
/// parse_infix_psl() as a parse_error exception.
|
||||
SPOT_API formula
|
||||
parse_formula(const std::string& ltl_string,
|
||||
environment& env = default_environment::instance());
|
||||
environment& env = default_environment::instance());
|
||||
|
||||
/// \brief Build a formula from a string representing a SERE.
|
||||
/// \param sere_string The string to parse.
|
||||
|
|
@ -200,10 +200,10 @@ namespace spot
|
|||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
parsed_formula parse_infix_sere(const std::string& sere_string,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
|
||||
/// \brief Fix location of diagnostics assuming the input is utf8.
|
||||
///
|
||||
|
|
@ -230,7 +230,7 @@ namespace spot
|
|||
SPOT_API
|
||||
void
|
||||
fix_utf8_locations(const std::string& input_string,
|
||||
parse_error_list& error_list);
|
||||
parse_error_list& error_list);
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
1218
spot/tl/print.cc
1218
spot/tl/print.cc
File diff suppressed because it is too large
Load diff
|
|
@ -34,14 +34,14 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_psl(std::ostream& os, formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Convert a PSL formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_psl(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -49,15 +49,15 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_utf8_psl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert a PSL formula into a utf-8 string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_utf8_psl(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -65,14 +65,14 @@ namespace spot
|
|||
/// \param f The formula to translate.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sere(std::ostream& os, formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Convert a SERE formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sere(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -80,15 +80,15 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_utf8_sere(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert a SERE formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_utf8_sere(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -96,15 +96,15 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_spin_ltl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert an LTL formula into a string parsable by Spin.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_spin_ltl(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -123,16 +123,16 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_latex_psl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a formula as a LaTeX string which is parsable.
|
||||
/// unless the formula contains automaton operators (used in ELTL formulae).
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_latex_psl(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -140,16 +140,16 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_latex_sere(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a LaTeX string which is parsable.
|
||||
/// unless the formula contains automaton operators (used in ELTL formulae).
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_latex_sere(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -159,17 +159,17 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sclatex_psl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a PSL formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed bacl.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sclatex_psl(formula f, bool full_parent = false);
|
||||
|
||||
|
|
@ -179,17 +179,17 @@ namespace spot
|
|||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sclatex_sere(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed bacl.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sclatex_sere(formula f, bool full_parent = false);
|
||||
|
||||
|
|
|
|||
|
|
@ -183,24 +183,24 @@ namespace spot
|
|||
total_2_and_more_ = 0.0;
|
||||
for (unsigned i = 0; i < proba_size_; ++i)
|
||||
{
|
||||
if (proba_[i].min_n == 1)
|
||||
{
|
||||
total_1_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_)
|
||||
total_2_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_or_more_)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
}
|
||||
else if (proba_[i].min_n == 2)
|
||||
{
|
||||
total_2_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_or_more_)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
}
|
||||
else if (proba_[i].min_n > 2)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
else
|
||||
SPOT_UNREACHABLE(); // unexpected max_n
|
||||
if (proba_[i].min_n == 1)
|
||||
{
|
||||
total_1_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_)
|
||||
total_2_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_or_more_)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
}
|
||||
else if (proba_[i].min_n == 2)
|
||||
{
|
||||
total_2_ += proba_[i].proba;
|
||||
if (proba_ + i >= proba_2_or_more_)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
}
|
||||
else if (proba_[i].min_n > 2)
|
||||
total_2_and_more_ += proba_[i].proba;
|
||||
else
|
||||
SPOT_UNREACHABLE(); // unexpected max_n
|
||||
}
|
||||
assert(total_2_and_more_ >= total_2_);
|
||||
}
|
||||
|
|
@ -216,48 +216,48 @@ namespace spot
|
|||
// Approximate impossible cases.
|
||||
if (n == 1 && total_1_ == 0.0)
|
||||
{
|
||||
if (total_2_ != 0.0)
|
||||
n = 2;
|
||||
else
|
||||
n = 3;
|
||||
if (total_2_ != 0.0)
|
||||
n = 2;
|
||||
else
|
||||
n = 3;
|
||||
}
|
||||
else if (n == 2 && total_2_ == 0.0)
|
||||
{
|
||||
if (total_1_ != 0.0)
|
||||
n = 1;
|
||||
else
|
||||
n = 3;
|
||||
if (total_1_ != 0.0)
|
||||
n = 1;
|
||||
else
|
||||
n = 3;
|
||||
}
|
||||
else if (n > 2 && total_2_and_more_ == 0.0)
|
||||
{
|
||||
if (total_1_ != 0.0)
|
||||
n = 1;
|
||||
else
|
||||
assert(total_2_ == 0.0);
|
||||
if (total_1_ != 0.0)
|
||||
n = 1;
|
||||
else
|
||||
assert(total_2_ == 0.0);
|
||||
}
|
||||
|
||||
|
||||
if (n == 1)
|
||||
{
|
||||
r *= total_1_;
|
||||
p = proba_;
|
||||
r *= total_1_;
|
||||
p = proba_;
|
||||
}
|
||||
else if (n == 2)
|
||||
{
|
||||
r *= total_2_;
|
||||
p = proba_2_;
|
||||
r *= total_2_;
|
||||
p = proba_2_;
|
||||
}
|
||||
else
|
||||
{
|
||||
r *= total_2_and_more_;
|
||||
p = proba_2_or_more_;
|
||||
r *= total_2_and_more_;
|
||||
p = proba_2_or_more_;
|
||||
}
|
||||
|
||||
double s = p->proba;
|
||||
while (s < r)
|
||||
{
|
||||
++p;
|
||||
s += p->proba;
|
||||
++p;
|
||||
s += p->proba;
|
||||
}
|
||||
|
||||
return p->build(this, n);
|
||||
|
|
@ -271,30 +271,30 @@ namespace spot
|
|||
char* key = strtok(options, "=\t, :;");
|
||||
while (key)
|
||||
{
|
||||
char* value = strtok(nullptr, "=\t, :;");
|
||||
if (!value)
|
||||
return key;
|
||||
char* value = strtok(nullptr, "=\t, :;");
|
||||
if (!value)
|
||||
return key;
|
||||
|
||||
char* endptr;
|
||||
double res = strtod(value, &endptr);
|
||||
if (*endptr)
|
||||
return value;
|
||||
char* endptr;
|
||||
double res = strtod(value, &endptr);
|
||||
if (*endptr)
|
||||
return value;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < proba_size_; ++i)
|
||||
{
|
||||
if (('a' <= *proba_[i].name && *proba_[i].name <= 'z'
|
||||
&& !strcasecmp(proba_[i].name, key))
|
||||
|| !strcmp(proba_[i].name, key))
|
||||
{
|
||||
proba_[i].proba = res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == proba_size_)
|
||||
return key;
|
||||
unsigned i;
|
||||
for (i = 0; i < proba_size_; ++i)
|
||||
{
|
||||
if (('a' <= *proba_[i].name && *proba_[i].name <= 'z'
|
||||
&& !strcasecmp(proba_[i].name, key))
|
||||
|| !strcmp(proba_[i].name, key))
|
||||
{
|
||||
proba_[i].proba = res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == proba_size_)
|
||||
return key;
|
||||
|
||||
key = strtok(nullptr, "=\t, :;");
|
||||
key = strtok(nullptr, "=\t, :;");
|
||||
}
|
||||
update_sums();
|
||||
return nullptr;
|
||||
|
|
@ -393,7 +393,7 @@ namespace spot
|
|||
{
|
||||
// FIXME: This looks very fragile.
|
||||
memmove(proba_ + 8, proba_ + 7,
|
||||
((proba_ + 16) - (proba_ + 7)) * sizeof(*proba_));
|
||||
((proba_ + 16) - (proba_ + 7)) * sizeof(*proba_));
|
||||
|
||||
proba_[7].setup("Closure", 2, closure_builder);
|
||||
proba_[17].setup("EConcat", 3, binop_SERELTL_builder<op::EConcat>);
|
||||
|
|
@ -402,10 +402,10 @@ namespace spot
|
|||
}
|
||||
|
||||
randltlgenerator::randltlgenerator(atomic_prop_set aprops,
|
||||
const option_map& opts,
|
||||
char* opt_pL,
|
||||
char* opt_pS,
|
||||
char* opt_pB)
|
||||
const option_map& opts,
|
||||
char* opt_pL,
|
||||
char* opt_pS,
|
||||
char* opt_pB)
|
||||
{
|
||||
aprops_ = aprops;
|
||||
output_ = opts.get("output", OUTPUTLTL);
|
||||
|
|
@ -423,51 +423,51 @@ namespace spot
|
|||
switch (output_)
|
||||
{
|
||||
case OUTPUTLTL:
|
||||
rf_ = new random_ltl(&aprops_);
|
||||
if (opt_pS)
|
||||
throw std::invalid_argument("Cannot set sere priorities with "
|
||||
"LTL output");
|
||||
if (opt_pB)
|
||||
throw std::invalid_argument("Cannot set boolean priorities with "
|
||||
"LTL output");
|
||||
tok_pL = rf_->parse_options(opt_pL);
|
||||
break;
|
||||
rf_ = new random_ltl(&aprops_);
|
||||
if (opt_pS)
|
||||
throw std::invalid_argument("Cannot set sere priorities with "
|
||||
"LTL output");
|
||||
if (opt_pB)
|
||||
throw std::invalid_argument("Cannot set boolean priorities with "
|
||||
"LTL output");
|
||||
tok_pL = rf_->parse_options(opt_pL);
|
||||
break;
|
||||
case OUTPUTBOOL:
|
||||
rf_ = new random_boolean(&aprops_);
|
||||
tok_pB = rf_->parse_options(opt_pB);
|
||||
if (opt_pL)
|
||||
throw std::invalid_argument("Cannot set ltl priorities with "
|
||||
"Boolean output");
|
||||
if (opt_pS)
|
||||
throw std::invalid_argument("Cannot set sere priorities "
|
||||
"with Boolean output");
|
||||
break;
|
||||
rf_ = new random_boolean(&aprops_);
|
||||
tok_pB = rf_->parse_options(opt_pB);
|
||||
if (opt_pL)
|
||||
throw std::invalid_argument("Cannot set ltl priorities with "
|
||||
"Boolean output");
|
||||
if (opt_pS)
|
||||
throw std::invalid_argument("Cannot set sere priorities "
|
||||
"with Boolean output");
|
||||
break;
|
||||
case OUTPUTSERE:
|
||||
rf_ = rs_ = new random_sere(&aprops_);
|
||||
tok_pS = rs_->parse_options(opt_pS);
|
||||
tok_pB = rs_->rb.parse_options(opt_pB);
|
||||
if (opt_pL)
|
||||
throw std::invalid_argument("Cannot set ltl priorities "
|
||||
"with SERE output");
|
||||
break;
|
||||
rf_ = rs_ = new random_sere(&aprops_);
|
||||
tok_pS = rs_->parse_options(opt_pS);
|
||||
tok_pB = rs_->rb.parse_options(opt_pB);
|
||||
if (opt_pL)
|
||||
throw std::invalid_argument("Cannot set ltl priorities "
|
||||
"with SERE output");
|
||||
break;
|
||||
case OUTPUTPSL:
|
||||
rf_ = rp_ = new random_psl(&aprops_);
|
||||
rs_ = &rp_->rs;
|
||||
tok_pL = rp_->parse_options(opt_pL);
|
||||
tok_pS = rs_->parse_options(opt_pS);
|
||||
tok_pB = rs_->rb.parse_options(opt_pB);
|
||||
break;
|
||||
rf_ = rp_ = new random_psl(&aprops_);
|
||||
rs_ = &rp_->rs;
|
||||
tok_pL = rp_->parse_options(opt_pL);
|
||||
tok_pS = rs_->parse_options(opt_pS);
|
||||
tok_pB = rs_->rb.parse_options(opt_pB);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tok_pL)
|
||||
throw std::invalid_argument("failed to parse LTL priorities near "
|
||||
+ std::string(tok_pL));
|
||||
+ std::string(tok_pL));
|
||||
if (tok_pS)
|
||||
throw std::invalid_argument("failed to parse SERE priorities near "
|
||||
+ std::string(tok_pS));
|
||||
+ std::string(tok_pS));
|
||||
if (tok_pB)
|
||||
throw std::invalid_argument("failed to parse Boolean priorities near "
|
||||
+ std::string(tok_pB));
|
||||
+ std::string(tok_pB));
|
||||
|
||||
spot::srand(opt_seed_);
|
||||
tl_simplifier_options simpl_opts(opt_simpl_level_);
|
||||
|
|
@ -475,12 +475,12 @@ namespace spot
|
|||
}
|
||||
|
||||
randltlgenerator::randltlgenerator(int aprops_n,
|
||||
const option_map& opts,
|
||||
char* opt_pL,
|
||||
char* opt_pS,
|
||||
char* opt_pB)
|
||||
const option_map& opts,
|
||||
char* opt_pL,
|
||||
char* opt_pS,
|
||||
char* opt_pB)
|
||||
: randltlgenerator(create_atomic_prop_set(aprops_n), opts,
|
||||
opt_pL, opt_pS, opt_pB)
|
||||
opt_pL, opt_pS, opt_pB)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -496,24 +496,24 @@ namespace spot
|
|||
formula f = nullptr;
|
||||
do
|
||||
{
|
||||
ignore = false;
|
||||
int size = opt_tree_size_min_;
|
||||
if (size != opt_tree_size_max_)
|
||||
size = spot::rrand(size, opt_tree_size_max_);
|
||||
f = rf_->generate(size);
|
||||
ignore = false;
|
||||
int size = opt_tree_size_min_;
|
||||
if (size != opt_tree_size_max_)
|
||||
size = spot::rrand(size, opt_tree_size_max_);
|
||||
f = rf_->generate(size);
|
||||
|
||||
if (opt_wf_)
|
||||
{
|
||||
atomic_prop_set s = aprops_;
|
||||
remove_some_props(s);
|
||||
f = formula::And({f, GF_n()});
|
||||
}
|
||||
if (opt_wf_)
|
||||
{
|
||||
atomic_prop_set s = aprops_;
|
||||
remove_some_props(s);
|
||||
f = formula::And({f, GF_n()});
|
||||
}
|
||||
|
||||
if (opt_simpl_level_)
|
||||
f = simpl_.simplify(f);
|
||||
if (opt_simpl_level_)
|
||||
f = simpl_.simplify(f);
|
||||
|
||||
if (opt_unique_ && !unique_set_.insert(f).second)
|
||||
ignore = true;
|
||||
if (opt_unique_ && !unique_set_.insert(f).second)
|
||||
ignore = true;
|
||||
} while (ignore && --trials);
|
||||
if (trials <= 0)
|
||||
return nullptr;
|
||||
|
|
@ -529,9 +529,9 @@ namespace spot
|
|||
|
||||
while (n--)
|
||||
{
|
||||
auto i = s.begin();
|
||||
std::advance(i, spot::mrand(s.size()));
|
||||
s.erase(i);
|
||||
auto i = s.begin();
|
||||
std::advance(i, spot::mrand(s.size()));
|
||||
s.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -542,11 +542,11 @@ namespace spot
|
|||
formula res = nullptr;
|
||||
for (auto v: aprops_)
|
||||
{
|
||||
formula f = formula::G(formula::F(v));
|
||||
if (res)
|
||||
res = formula::And({f, res});
|
||||
else
|
||||
res = f;
|
||||
formula f = formula::G(formula::F(v));
|
||||
if (res)
|
||||
res = formula::And({f, res});
|
||||
else
|
||||
res = f;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue