bin: allow %l to be used to print serial numbers

* NEWS: Mention it.
* bin/autfilt.cc, bin/common_aoutput.cc, bin/common_aoutput.hh,
bin/common_output.cc, bin/common_output.hh, bin/dstar2tgba.cc,
bin/genaut.cc, bin/genltl.cc, bin/ltl2tgba.cc, bin/ltldo.cc,
bin/ltlfilt.cc, bin/ltlgrind.cc, bin/randaut.cc, bin/randltl.cc:
Implement it.
* doc/org/oaut.org: Add a short example.
* tests/core/serial.test: New file.
* tests/Makefile.am: Add it.
This commit is contained in:
Alexandre Duret-Lutz 2023-07-21 17:06:01 +02:00
parent 8369663380
commit 61b457a37e
18 changed files with 183 additions and 41 deletions

View file

@ -1680,8 +1680,6 @@ namespace
return 0;
}
++match_count;
if (aliases)
{
if (opt_aliases)
@ -1690,7 +1688,9 @@ namespace
set_aliases(aut, {});
}
printer.print(aut, timer, nullptr, haut->filename.c_str(), -1,
haut, prefix, suffix);
match_count, haut, prefix, suffix);
++match_count;
if (opt_max_count >= 0 && match_count >= opt_max_count)
abort_run = true;

View file

@ -198,6 +198,8 @@ static const argp_option io_options[] =
" minuscules for output):", 4 },
{ "%F", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, F_doc, 0 },
{ "%L", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, L_doc, 0 },
{ "%l", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"serial number of the output automaton (0-based)", 0 },
{ "%H, %h", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the automaton in HOA format on a single line (use %[opt]H or %[opt]h "
"to specify additional options as in --hoa=opt)", 0 },
@ -269,6 +271,8 @@ static const argp_option o_options[] =
"the following interpreted sequences:", 4 },
{ "%F", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, F_doc, 0 },
{ "%L", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, L_doc, 0 },
{ "%l", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"serial number of the output automaton (0-based)", 0 },
{ "%h", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the automaton in HOA format on a single line (use %[opt]h "
"to specify additional options as in --hoa=opt)", 0 },
@ -442,6 +446,7 @@ hoa_stat_printer::hoa_stat_printer(std::ostream& os, const char* format,
if (input != ltl_input)
declare('f', &filename_); // Override the formula printer.
declare('h', &output_aut_);
declare('l', &index_);
declare('m', &aut_name_);
declare('u', &aut_univbranch_);
declare('w', &aut_word_);
@ -453,11 +458,12 @@ hoa_stat_printer::print(const spot::const_parsed_aut_ptr& haut,
const spot::const_twa_graph_ptr& aut,
spot::formula f,
const char* filename, int loc,
unsigned index,
const spot::process_timer& ptimer,
const char* csv_prefix, const char* csv_suffix)
{
timer_ = ptimer;
index_ = index;
filename_ = filename ? filename : "";
csv_prefix_ = csv_prefix ? csv_prefix : "";
csv_suffix_ = csv_suffix ? csv_suffix : "";
@ -599,6 +605,7 @@ automaton_printer::print(const spot::twa_graph_ptr& aut,
// Input location for errors and statistics.
const char* filename,
int loc,
unsigned index,
// input automaton for statistics
const spot::const_parsed_aut_ptr& haut,
const char* csv_prefix,
@ -622,7 +629,8 @@ automaton_printer::print(const spot::twa_graph_ptr& aut,
if (opt_name)
{
name.str("");
namer.print(haut, aut, f, filename, loc, ptimer, csv_prefix, csv_suffix);
namer.print(haut, aut, f, filename, loc, index,
ptimer, csv_prefix, csv_suffix);
aut->set_named_prop("automaton-name", new std::string(name.str()));
}
@ -630,8 +638,8 @@ automaton_printer::print(const spot::twa_graph_ptr& aut,
if (opt_output)
{
outputname.str("");
outputnamer.print(haut, aut, f, filename, loc, ptimer,
csv_prefix, csv_suffix);
outputnamer.print(haut, aut, f, filename, loc, index,
ptimer, csv_prefix, csv_suffix);
std::string fname = outputname.str();
auto [it, b] = outputfiles.try_emplace(fname, nullptr);
if (b)
@ -660,8 +668,8 @@ automaton_printer::print(const spot::twa_graph_ptr& aut,
break;
case Stats:
statistics.set_output(*out);
statistics.print(haut, aut, f, filename, loc, ptimer,
csv_prefix, csv_suffix) << '\n';
statistics.print(haut, aut, f, filename, loc, index,
ptimer, csv_prefix, csv_suffix) << '\n';
break;
}
flush_cout();

View file

@ -133,10 +133,10 @@ public:
void print(std::ostream& os, const char* pos) const override;
};
/// \brief prints various statistics about a TGBA
/// \brief prints various statistics about a TwA
///
/// This object can be configured to display various statistics
/// about a TGBA. Some %-sequence of characters are interpreted in
/// about a TwA. Some %-sequence of characters are interpreted in
/// the format string, and replaced by the corresponding statistics.
class hoa_stat_printer: protected spot::stat_printer
{
@ -153,10 +153,12 @@ 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, const spot::process_timer& ptimer,
const char* csv_prefix, const char* csv_suffix);
const spot::const_twa_graph_ptr& aut,
spot::formula f,
const char* filename, int loc,
unsigned index,
const spot::process_timer& ptimer,
const char* csv_prefix, const char* csv_suffix);
private:
spot::printable_value<const char*> filename_;
@ -165,6 +167,7 @@ private:
spot::printable_value<std::string> aut_name_;
spot::printable_value<std::string> aut_word_;
spot::printable_value<std::string> haut_word_;
spot::printable_value<unsigned> index_;
spot::printable_acc_cond haut_gen_acc_;
spot::printable_size haut_states_;
spot::printable_size haut_edges_;
@ -206,6 +209,8 @@ public:
// Input location for errors and statistics.
const char* filename = nullptr,
int loc = -1,
// serial numbner
unsigned index = 0,
// Time and input automaton for statistics
const spot::const_parsed_aut_ptr& haut = nullptr,
const char* csv_prefix = nullptr,

View file

@ -160,6 +160,7 @@ namespace
spot::formula f;
const char* filename;
const char* line;
unsigned index;
const char* prefix;
const char* suffix;
};
@ -237,6 +238,7 @@ namespace
declare('R', &timer_);
declare('r', &timer_);
declare('L', &line_);
declare('l', &index_);
declare('s', &size_);
declare('h', &class_);
declare('n', &nesting_);
@ -248,7 +250,8 @@ namespace
}
std::ostream&
print(const formula_with_location& fl, spot::process_timer* ptimer)
print(const formula_with_location& fl,
spot::process_timer* ptimer)
{
if (has('R') || has('r'))
timer_ = *ptimer;
@ -256,6 +259,7 @@ namespace
fl_ = &fl;
filename_ = fl.filename ? fl.filename : "";
line_ = fl.line;
index_ = fl.index;
prefix_ = fl.prefix ? fl.prefix : "";
suffix_ = fl.suffix ? fl.suffix : "";
auto f = fl_.val()->f;
@ -288,6 +292,7 @@ namespace
printable_timer timer_;
spot::printable_value<const char*> filename_;
spot::printable_value<const char*> line_;
spot::printable_value<unsigned> index_;
spot::printable_value<const char*> prefix_;
spot::printable_value<const char*> suffix_;
spot::printable_value<int> size_;
@ -356,6 +361,7 @@ static void
output_formula(std::ostream& out,
spot::formula f, spot::process_timer* ptimer,
const char* filename, const char* linenum,
unsigned index,
const char* prefix, const char* suffix)
{
if (!format)
@ -391,7 +397,8 @@ output_formula(std::ostream& out,
}
else
{
formula_with_location fl = { f, filename, linenum, prefix, suffix };
formula_with_location fl = { f, filename, linenum,
index, prefix, suffix };
format->print(fl, ptimer);
}
}
@ -399,6 +406,7 @@ output_formula(std::ostream& out,
void
output_formula_checked(spot::formula f, spot::process_timer* ptimer,
const char* filename, const char* linenum,
unsigned index,
const char* prefix, const char* suffix)
{
if (output_format == count_output)
@ -414,7 +422,8 @@ output_formula_checked(spot::formula f, spot::process_timer* ptimer,
if (outputnamer)
{
outputname.str("");
formula_with_location fl = { f, filename, linenum, prefix, suffix };
formula_with_location fl = { f, filename, linenum,
index, prefix, suffix };
outputnamer->print(fl, ptimer);
std::string fname = outputname.str();
auto [it, b] = outputfiles.try_emplace(fname, nullptr);
@ -422,7 +431,7 @@ output_formula_checked(spot::formula f, spot::process_timer* ptimer,
it->second.reset(new output_file(fname.c_str()));
out = &it->second->ostream();
}
output_formula(*out, f, ptimer, filename, linenum, prefix, suffix);
output_formula(*out, f, ptimer, filename, linenum, index, prefix, suffix);
*out << output_terminator;
// Make sure we abort if we can't write to std::cout anymore
// (like disk full or broken pipe with SIGPIPE ignored).
@ -432,10 +441,12 @@ output_formula_checked(spot::formula f, spot::process_timer* ptimer,
void output_formula_checked(spot::formula f,
spot::process_timer* ptimer,
const char* filename, int linenum,
unsigned index,
const char* prefix,
const char* suffix)
{
output_formula_checked(f, ptimer, filename,
std::to_string(linenum).c_str(),
index,
prefix, suffix);
}

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2012-2018 Laboratoire de Recherche et Développement
// Copyright (C) 2012-2018, 2023 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -81,11 +81,13 @@ void output_formula_checked(spot::formula f,
spot::process_timer* ptimer = nullptr,
const char* filename = nullptr,
const char* linenum = nullptr,
unsigned output_index = 0U,
const char* prefix = nullptr,
const char* suffix = nullptr);
void output_formula_checked(spot::formula f,
spot::process_timer* ptimer,
const char* filename, int linenum,
unsigned output_index,
const char* prefix = nullptr,
const char* suffix = nullptr);

View file

@ -129,7 +129,9 @@ namespace
timer.start();
auto aut = post.run(haut->aut, nullptr);
timer.stop();
printer.print(aut, timer, nullptr, haut->filename.c_str(), -1, haut);
static unsigned index = 0;
printer.print(aut, timer, nullptr, haut->filename.c_str(), -1,
index++, haut);
flush_cout();
return 0;
}

View file

@ -122,7 +122,8 @@ output_pattern(gen::aut_pattern_id pattern, int n)
twa_graph_ptr aut = spot::gen::aut_pattern(pattern, n);
timer.stop();
automaton_printer printer;
printer.print(aut, timer, nullptr, aut_pattern_name(pattern), n);
static unsigned serial = 0;
printer.print(aut, timer, nullptr, aut_pattern_name(pattern), n, serial++);
}
static void

View file

@ -192,6 +192,8 @@ static const argp_option options[] =
"the formula (in the selected syntax)", 0 },
{ "%F", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the name of the pattern", 0 },
{ "%l", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"serial number of the output formula (0-based)", 0 },
{ "%L", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the argument of the pattern", 0 },
{ "%%", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
@ -287,6 +289,8 @@ parse_opt(int key, char* arg, struct argp_state*)
}
static unsigned output_count = 0U;
static void
output_pattern(gen::ltl_pattern_id pattern, int n, int n2)
{
@ -303,14 +307,14 @@ output_pattern(gen::ltl_pattern_id pattern, int n, int n2)
if (opt_positive || !opt_negative)
{
output_formula_checked(f, nullptr, gen::ltl_pattern_name(pattern),
args.c_str());
args.c_str(), output_count++);
}
if (opt_negative)
{
std::string tmp = "!";
tmp += gen::ltl_pattern_name(pattern);
output_formula_checked(formula::Not(f), nullptr, tmp.c_str(),
args.c_str());
args.c_str(), output_count++);
}
}

View file

@ -155,8 +155,9 @@ namespace
auto aut = trans.run(&f);
timer.stop();
printer.print(aut, timer, f, filename, linenum, nullptr,
prefix, suffix);
static unsigned index = 0;
printer.print(aut, timer, f, filename, linenum, index++,
nullptr, prefix, suffix);
// If we keep simplification caches around, atomic propositions
// will still be defined, and one translation may influence the
// variable order of the next one.

View file

@ -360,8 +360,7 @@ namespace
const char* csv_prefix, const char* csv_suffix)
{
static long int output_count = 0;
++output_count;
printer.print(aut, ptimer, f, filename, loc, nullptr,
printer.print(aut, ptimer, f, filename, loc, output_count++, nullptr,
csv_prefix, csv_suffix);
if (opt_max_count >= 0 && output_count >= opt_max_count)
abort_run = true;
@ -420,8 +419,8 @@ namespace
aut = post.run(aut, f);
if (best_type)
{
best_printer.print(nullptr, aut, f, filename, linenum, timer,
prefix, suffix);
best_printer.print(nullptr, aut, f, filename, linenum, 0,
timer, prefix, suffix);
std::string aut_stats = best_stream.str();
if (!best_aut ||
(strverscmp(best_stats.c_str(), aut_stats.c_str())

View file

@ -254,6 +254,8 @@ static const argp_option options[] =
"the formula (in the selected syntax)", 0 },
{ "%F", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the name of the input file", 0 },
{ "%l", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the serial number of the output formula", 0 },
{ "%L", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the original line number in the input file", 0 },
{ "%r", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
@ -852,7 +854,8 @@ namespace
std::to_string(linenum).c_str()) << ")\n";
}
one_match = true;
output_formula_checked(f, &timer, filename, linenum, prefix, suffix);
output_formula_checked(f, &timer, filename, linenum,
match_count, prefix, suffix);
++match_count;
}
return 0;

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2014-2019, 2022 Laboratoire de Recherche et
// Copyright (C) 2014-2019, 2022, 2023 Laboratoire de Recherche et
// Développement de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -87,6 +87,8 @@ static const argp_option options[] = {
"the formula (in the selected syntax)", 0 },
{ "%F", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the name of the input file", 0 },
{ "%l", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the serial number of the output formula (0-based)", 0 },
{ "%L", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the original line number in the input file", 0 },
{ "%<", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
@ -112,6 +114,8 @@ static const argp_child children[] = {
namespace
{
static unsigned output_count = 0;
class mutate_processor final: public job_processor
{
public:
@ -122,7 +126,8 @@ namespace
auto mutations =
spot::mutate(f, mut_opts, max_output, mutation_nb, opt_sort);
for (auto g: mutations)
output_formula_checked(g, nullptr, filename, linenum, prefix, suffix);
output_formula_checked(g, nullptr, filename, linenum,
output_count++, prefix, suffix);
return 0;
}
};

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2012-2016, 2018-2020, 2022 Laboratoire de Recherche
// Copyright (C) 2012-2016, 2018-2020, 2022, 2023 Laboratoire de Recherche
// et Développement de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -406,7 +406,8 @@ main(int argc, char** argv)
timer.stop();
printer.print(aut, timer, nullptr,
opt_seed_str, automaton_num, nullptr);
opt_seed_str, automaton_num,
automaton_num, nullptr);
++automaton_num;
if (opt_automata > 0 && automaton_num >= opt_automata)

View file

@ -115,8 +115,10 @@ static const argp_option options[] =
"the following interpreted sequences:", -19 },
{ "%f", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the formula (in the selected syntax)", 0 },
{ "%l", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the (serial) number of the formula (0-based)", 0 },
{ "%L", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"the (serial) number of the formula", 0 },
"the (serial) number of the formula (1-based)", 0 },
{ "%%", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"a single %", 0 },
COMMON_LTL_OUTPUT_SPECS,
@ -305,9 +307,9 @@ main(int argc, char** argv)
exit(0);
}
int count = 0;
while (opt_formulas < 0 || opt_formulas--)
{
static int count = 0;
spot::formula f = rg.next();
if (!f)
{
@ -316,7 +318,8 @@ main(int argc, char** argv)
}
else
{
output_formula_checked(f, nullptr, nullptr, ++count);
output_formula_checked(f, nullptr, nullptr, count + 1, count);
++count;
}
};
flush_cout();