ltlcross: add support for --reference translators
Suggested by Tobias Meggendorfer. Fixes #295. * bin/ltlcross.cc, bin/common_trans.hh, bin/common_trans.cc: Implement this --reference option. * NEWS, doc/org/ltlcross.org: Document it. * tests/core/ltlcross3.test: Test it.
This commit is contained in:
parent
77c0e76258
commit
fcccd5f425
6 changed files with 278 additions and 28 deletions
|
|
@ -81,8 +81,9 @@ static void show_shorthands(shorthands_t* begin, shorthands_t* end)
|
|||
}
|
||||
|
||||
|
||||
tool_spec::tool_spec(const char* spec, shorthands_t* begin, shorthands_t* end)
|
||||
: spec(spec), cmd(spec), name(spec)
|
||||
tool_spec::tool_spec(const char* spec, shorthands_t* begin, shorthands_t* end,
|
||||
bool is_ref)
|
||||
: spec(spec), cmd(spec), name(spec), reference(is_ref)
|
||||
{
|
||||
if (*cmd == '{')
|
||||
{
|
||||
|
|
@ -144,7 +145,8 @@ tool_spec::tool_spec(const char* spec, shorthands_t* begin, shorthands_t* end)
|
|||
}
|
||||
|
||||
tool_spec::tool_spec(const tool_spec& other)
|
||||
: spec(other.spec), cmd(other.cmd), name(other.name)
|
||||
: spec(other.spec), cmd(other.cmd), name(other.name),
|
||||
reference(other.reference)
|
||||
{
|
||||
if (cmd != spec)
|
||||
cmd = strdup(cmd);
|
||||
|
|
@ -174,18 +176,20 @@ tool_spec::~tool_spec()
|
|||
|
||||
std::vector<tool_spec> tools;
|
||||
|
||||
void tools_push_trans(const char* trans)
|
||||
void tools_push_trans(const char* trans, bool is_ref)
|
||||
{
|
||||
tools.emplace_back(trans,
|
||||
std::begin(shorthands_ltl),
|
||||
std::end(shorthands_ltl));
|
||||
std::end(shorthands_ltl),
|
||||
is_ref);
|
||||
}
|
||||
|
||||
void tools_push_autproc(const char* proc)
|
||||
void tools_push_autproc(const char* proc, bool is_ref)
|
||||
{
|
||||
tools.emplace_back(proc,
|
||||
std::begin(shorthands_autproc),
|
||||
std::end(shorthands_autproc));
|
||||
std::end(shorthands_autproc),
|
||||
is_ref);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -47,8 +47,11 @@ struct tool_spec
|
|||
const char* cmd;
|
||||
// name of the translator (or spec)
|
||||
const char* name;
|
||||
// Whether the tool is a reference.
|
||||
bool reference;
|
||||
|
||||
tool_spec(const char* spec, shorthands_t* begin, shorthands_t* end);
|
||||
tool_spec(const char* spec, shorthands_t* begin, shorthands_t* end,
|
||||
bool is_ref);
|
||||
tool_spec(const tool_spec& other);
|
||||
tool_spec& operator=(const tool_spec& other);
|
||||
~tool_spec();
|
||||
|
|
@ -56,8 +59,8 @@ struct tool_spec
|
|||
|
||||
extern std::vector<tool_spec> tools;
|
||||
|
||||
void tools_push_trans(const char* trans);
|
||||
void tools_push_autproc(const char* proc);
|
||||
void tools_push_trans(const char* trans, bool is_ref = false);
|
||||
void tools_push_autproc(const char* proc, bool is_ref = false);
|
||||
|
||||
struct quoted_string final: public spot::printable_value<std::string>
|
||||
{
|
||||
|
|
|
|||
102
bin/ltlcross.cc
102
bin/ltlcross.cc
|
|
@ -95,6 +95,7 @@ enum {
|
|||
OPT_NOCOMP,
|
||||
OPT_OMIT,
|
||||
OPT_PRODUCTS,
|
||||
OPT_REFERENCE,
|
||||
OPT_SEED,
|
||||
OPT_STATES,
|
||||
OPT_STOP_ERR,
|
||||
|
|
@ -104,6 +105,9 @@ enum {
|
|||
|
||||
static const argp_option options[] =
|
||||
{
|
||||
{ "reference", OPT_REFERENCE, "COMMANDFMT", 0,
|
||||
"register one translator and assume it is correct (do not"
|
||||
"check it for error, but use it to check other translators)", 2 },
|
||||
/**************************************************/
|
||||
{ nullptr, 0, nullptr, 0, "ltlcross behavior:", 5 },
|
||||
{ "allow-dups", OPT_DUPS, nullptr, 0,
|
||||
|
|
@ -482,6 +486,9 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
case OPT_OMIT:
|
||||
opt_omit = true;
|
||||
break;
|
||||
case OPT_REFERENCE:
|
||||
tools_push_trans(arg, true);
|
||||
break;
|
||||
case OPT_SEED:
|
||||
seed = to_pos_int(arg);
|
||||
break;
|
||||
|
|
@ -1092,6 +1099,39 @@ namespace
|
|||
std::cerr << "Performing sanity checks and gathering statistics..."
|
||||
<< std::endl;
|
||||
|
||||
// If we have reference tools, pick the smallest of their
|
||||
// automata for positive and negative references.
|
||||
auto smallest_ref = [&](std::vector<spot::twa_graph_ptr>& from)
|
||||
{
|
||||
typedef std::tuple<bool, unsigned, unsigned, unsigned> aut_size;
|
||||
int smallest_ref = -1;
|
||||
aut_size smallest_size(true, -1U, -1U, -1U);
|
||||
for (unsigned i = 0; i < m; ++i)
|
||||
if (tools[i].reference && from[i])
|
||||
{
|
||||
aut_size pisize(!is_deterministic(from[i]),
|
||||
from[i]->num_states(),
|
||||
from[i]->num_edges(),
|
||||
from[i]->num_sets());
|
||||
if (pisize < smallest_size)
|
||||
{
|
||||
smallest_ref = i;
|
||||
smallest_size = pisize;
|
||||
}
|
||||
}
|
||||
return smallest_ref;
|
||||
};
|
||||
|
||||
// This are not our definitive choice for reference
|
||||
// automata, because the sizes might change after we remove
|
||||
// alternation and Fin acceptance. But we need to know now
|
||||
// if we will have a pair of reference automata in order to
|
||||
// skip some of the constructions.
|
||||
int smallest_pos_ref = smallest_ref(pos);
|
||||
int smallest_neg_ref = smallest_ref(neg);
|
||||
if (smallest_pos_ref < 0 || smallest_neg_ref < 0)
|
||||
smallest_pos_ref = smallest_neg_ref = -1;
|
||||
|
||||
bool print_first = verbose;
|
||||
auto unalt = [&](std::vector<spot::twa_graph_ptr>& x,
|
||||
unsigned i, char prefix)
|
||||
|
|
@ -1126,11 +1166,15 @@ namespace
|
|||
comp[i] = dualize(x[i]);
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < m; ++i)
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
{
|
||||
unalt(pos, i, 'P');
|
||||
complement(pos, comp_pos, i);
|
||||
unalt(neg, i, 'N');
|
||||
// Do not complement reference automata if we have a
|
||||
// reference pair.
|
||||
if (smallest_pos_ref >= 0 && tools[i].reference)
|
||||
continue;
|
||||
complement(pos, comp_pos, i);
|
||||
complement(neg, comp_neg, i);
|
||||
}
|
||||
|
||||
|
|
@ -1138,11 +1182,15 @@ namespace
|
|||
{
|
||||
print_first = verbose;
|
||||
auto tmp = [&](std::vector<spot::twa_graph_ptr>& from,
|
||||
std::vector<spot::twa_graph_ptr>& to, unsigned i,
|
||||
std::vector<spot::twa_graph_ptr>& to, int i,
|
||||
char prefix)
|
||||
{
|
||||
if (from[i] && !to[i])
|
||||
{
|
||||
// Do not complement reference automata if we have a
|
||||
// reference pair.
|
||||
if (smallest_pos_ref >= 0 && tools[i].reference)
|
||||
return;
|
||||
if (print_first)
|
||||
{
|
||||
std::cerr << "info: complementing non-deterministic "
|
||||
|
|
@ -1207,7 +1255,7 @@ namespace
|
|||
cleanup_acceptance_here(x[i]);
|
||||
}
|
||||
};
|
||||
for (unsigned i = 0; i < m; ++i)
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
{
|
||||
tmp(pos, i, " P", " ");
|
||||
tmp(neg, i, " N", " ");
|
||||
|
|
@ -1215,14 +1263,40 @@ namespace
|
|||
tmp(comp_neg, i, "Comp(N", ")");
|
||||
}
|
||||
|
||||
if (smallest_pos_ref >= 0)
|
||||
{
|
||||
// Recompute the smallest references now, because removing
|
||||
// alternation and Fin acceptance might have changed the
|
||||
// sizes.
|
||||
smallest_pos_ref = smallest_ref(pos);
|
||||
smallest_neg_ref = smallest_ref(neg);
|
||||
|
||||
if (verbose)
|
||||
std::cerr << "info: P" << smallest_pos_ref
|
||||
<< " and N" << smallest_neg_ref << " assumed "
|
||||
<< "correct and used as references\n";
|
||||
}
|
||||
|
||||
// intersection test
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
if (pos[i])
|
||||
for (size_t j = 0; j < m; ++j)
|
||||
if (neg[j])
|
||||
{
|
||||
problems +=
|
||||
check_empty_prod(pos[i], neg[j], i, j, false, false);
|
||||
// Do not compare reference translators.
|
||||
if (tools[i].reference && tools[j].reference)
|
||||
continue;
|
||||
// If we have a reference pair, only compare
|
||||
// against that pair when i != j.
|
||||
if (i == j ||
|
||||
!((!tools[i].reference &&
|
||||
smallest_neg_ref >= 0 &&
|
||||
(size_t)smallest_neg_ref != j)
|
||||
|| (!tools[j].reference &&
|
||||
smallest_pos_ref >= 0 &&
|
||||
(size_t)smallest_pos_ref != i)))
|
||||
problems +=
|
||||
check_empty_prod(pos[i], neg[j], i, j, false, false);
|
||||
|
||||
// Deal with the extra complemented automata if we
|
||||
// have some.
|
||||
|
|
@ -1240,13 +1314,15 @@ namespace
|
|||
// translation was not deterministic.
|
||||
|
||||
if (i != j && comp_pos[j] && !comp_neg[j])
|
||||
problems +=
|
||||
check_empty_prod(pos[i], comp_pos[j],
|
||||
i, j, false, true);
|
||||
if (smallest_pos_ref < 0 || i == (size_t)smallest_pos_ref)
|
||||
problems +=
|
||||
check_empty_prod(pos[i], comp_pos[j],
|
||||
i, j, false, true);
|
||||
if (i != j && comp_neg[i] && !comp_pos[i])
|
||||
problems +=
|
||||
check_empty_prod(comp_neg[i], neg[j],
|
||||
i, j, true, false);
|
||||
if (smallest_neg_ref < 0 || j == (size_t)smallest_neg_ref)
|
||||
problems +=
|
||||
check_empty_prod(comp_neg[i], neg[j],
|
||||
i, j, true, false);
|
||||
if (comp_pos[i] && comp_neg[j] &&
|
||||
(i == j || (!comp_neg[i] && !comp_pos[j])))
|
||||
problems +=
|
||||
|
|
@ -1370,7 +1446,7 @@ namespace
|
|||
|
||||
// consistency check
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
if (pos_map[i] && neg_map[i])
|
||||
if (pos_map[i] && neg_map[i] && !tools[i].reference)
|
||||
{
|
||||
if (verbose)
|
||||
std::cerr << "info: consistency_check (P" << i
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue