ltlsynt: overhaul CSV output

Previous output was not very usable in presence of decomposed
specifications.  We now keep track of the number of parts, and also
prefix the columns names with "max_" or "sum_" to indicate how their
statistics are updated in presence of multiple part.  Other missing
statistics, like the size of the translated automaton, or maximal
number of colors seen in a game, have been added.

* spot/twaalgos/synthesis.hh (bench_var): Rename, augment, and
document each statistsic.
* spot/twaalgos/mealy_machine.cc, spot/twaalgos/synthesis.cc,
bin/ltlsynt.cc: Adjust to the new naming scheme.
* doc/org/ltlsynt.org: Show a CSV file, and document its columns.
* tests/core/ltlsynt-pgame.test, tests/core/ltlsynt2.test,
tests/core/ltlsynt.test: Adjust test cases.
* NEWS: Mention the backward incompatible change.
This commit is contained in:
Alexandre Duret-Lutz 2024-09-09 16:28:51 +02:00
parent b729aa3f30
commit 5488cb75c6
9 changed files with 352 additions and 164 deletions

View file

@ -4353,9 +4353,10 @@ namespace spot
if (si.verbose_stream)
*si.verbose_stream << "simplification took " << sw.stop()
<< " seconds\n";
si.bv->simplify_strat_time += sw.stop();
auto n_s_env = 0u;
auto n_e_env = 0u;
si.bv->sum_simplify_strat_time += sw.stop();
unsigned n_s_env = 0;
unsigned n_e_env = 0;
// If the strategy is split, count only the environment's states
if (auto sp = m->get_named_prop<region_t>("state-player"))
{
n_s_env = sp->size() - std::accumulate(sp->begin(),
@ -4365,15 +4366,22 @@ namespace spot
[&n_e_env, &sp](const auto& e)
{
n_e_env += (*sp)[e.src];
});
});
}
else
{
n_s_env = m->num_states();
n_e_env = m->num_edges();
}
si.bv->nb_simpl_strat_states += n_s_env;
si.bv->nb_simpl_strat_edges += n_e_env;
if (std::tie(si.bv->max_simpl_strat_states,
si.bv->max_simpl_strat_edges)
< std::tie(n_s_env, n_e_env))
{
si.bv->max_simpl_strat_states = n_s_env;
si.bv->max_simpl_strat_edges = n_e_env;
}
si.bv->sum_simpl_strat_states += n_s_env;
si.bv->sum_simpl_strat_edges += n_e_env;
}
}
}

View file

@ -1574,11 +1574,11 @@ namespace spot
// release the variables
// Release the pairs
for (auto pair_ptr : {replace_fwd,
replace_bkwd,
replace_in_fwd,
replace_in_bkwd,
replace_out_fwd,
replace_out_bkwd})
replace_bkwd,
replace_in_fwd,
replace_in_bkwd,
replace_out_fwd,
replace_out_bkwd})
bdd_freepair(pair_ptr);
aut->get_dict()->unregister_all_my_variables(&N);
@ -1602,17 +1602,17 @@ namespace spot
: sp;
switch (sp)
{
case (synthesis_info::splittype::EXPL):
{
case synthesis_info::splittype::EXPL:
return split_2step_expl_impl(aut, output_bdd, complete_env);
case (synthesis_info::splittype::SEMISYM):
case synthesis_info::splittype::SEMISYM:
return split_2step_sym_impl<false>(aut, output_bdd, complete_env);
case (synthesis_info::splittype::FULLYSYM):
case synthesis_info::splittype::FULLYSYM:
return split_2step_sym_impl<true>(aut, output_bdd, complete_env);
default:
throw std::runtime_error("split_2step_(): "
"Expected explicit splittype.");
}
}
}
} // End anonymous
@ -1826,13 +1826,29 @@ namespace spot
sw.start();
auto aut = trans.run(f);
if (bv)
bv->trans_time += sw.stop();
{
bv->sum_trans_time += sw.stop();
unsigned ns = aut->num_states();
unsigned ne = aut->num_edges();
unsigned nc = aut->num_sets();
unsigned na = aut->ap().size();
if (std::tie(bv->max_trans_states,
bv->max_trans_edges,
bv->max_trans_colors,
bv->max_trans_ap)
< std::tie(ns, ne, nc, na))
{
bv->max_trans_states = ns;
bv->max_trans_edges = ne;
bv->max_trans_colors = nc;
bv->max_trans_ap = na;
}
}
if (vs)
{
assert(bv);
*vs << "translating formula done in "
<< bv->trans_time << " seconds\n";
<< bv->sum_trans_time << " seconds\n";
*vs << "automaton has " << aut->num_states()
<< " states and " << aut->num_sets() << " colors\n";
}
@ -1879,20 +1895,20 @@ namespace spot
<< tmp->num_sets() << " colors\n";
tmp->merge_states();
if (bv)
bv->paritize_time += sw.stop();
bv->sum_paritize_time += sw.stop();
if (vs)
*vs << "simplification done\nDPA has "
<< tmp->num_states() << " states\n"
<< "determinization and simplification took "
<< bv->paritize_time << " seconds\n";
<< bv->sum_paritize_time << " seconds\n";
if (bv)
sw.start();
dpa = set_split(tmp);
if (bv)
bv->split_time += sw.stop();
bv->sum_split_time += sw.stop();
if (vs)
*vs << "split inputs and outputs done in " << bv->split_time
*vs << "split inputs and outputs done in " << bv->sum_split_time
<< " seconds\nautomaton has "
<< tmp->num_states() << " states\n";
break;
@ -1903,18 +1919,18 @@ namespace spot
sw.start();
aut->merge_states();
if (bv)
bv->paritize_time += sw.stop();
bv->sum_paritize_time += sw.stop();
if (vs)
*vs << "simplification done in " << bv->paritize_time
*vs << "simplification done in " << bv->sum_paritize_time
<< " seconds\nDPA has " << aut->num_states()
<< " states\n";
if (bv)
sw.start();
dpa = set_split(aut);
if (bv)
bv->split_time += sw.stop();
bv->sum_split_time += sw.stop();
if (vs)
*vs << "split inputs and outputs done in " << bv->split_time
*vs << "split inputs and outputs done in " << bv->sum_split_time
<< " seconds\nautomaton has "
<< dpa->num_states() << " states\n";
break;
@ -1924,9 +1940,9 @@ namespace spot
sw.start();
auto split = set_split(aut);
if (bv)
bv->split_time += sw.stop();
bv->sum_split_time += sw.stop();
if (vs)
*vs << "split inputs and outputs done in " << bv->split_time
*vs << "split inputs and outputs done in " << bv->sum_split_time
<< " seconds\nautomaton has "
<< split->num_states() << " states\n";
if (bv)
@ -1942,12 +1958,12 @@ namespace spot
// Merge states knows about players
dpa->merge_states();
if (bv)
bv->paritize_time += sw.stop();
bv->sum_paritize_time += sw.stop();
if (vs)
*vs << "simplification done\nDPA has "
<< dpa->num_states() << " states\n"
<< "determinization and simplification took "
<< bv->paritize_time << " seconds\n";
<< bv->sum_paritize_time << " seconds\n";
break;
}
case algo::ACD:
@ -1971,10 +1987,10 @@ namespace spot
else
dpa = acd_transform(aut);
if (bv)
bv->paritize_time += sw.stop();
bv->sum_paritize_time += sw.stop();
if (vs)
*vs << (gi.s == algo::ACD ? "ACD" : "LAR")
<< " construction done in " << bv->paritize_time
<< " construction done in " << bv->sum_paritize_time
<< " seconds\nDPA has "
<< dpa->num_states() << " states, "
<< dpa->num_sets() << " colors\n";
@ -1983,9 +1999,9 @@ namespace spot
sw.start();
dpa = set_split(dpa);
if (bv)
bv->split_time += sw.stop();
bv->sum_split_time += sw.stop();
if (vs)
*vs << "split inputs and outputs done in " << bv->split_time
*vs << "split inputs and outputs done in " << bv->sum_split_time
<< " seconds\nautomaton has "
<< dpa->num_states() << " states\n";
break;
@ -2045,6 +2061,7 @@ namespace spot
if (gi.bv)
{
gi.bv->sum_strat2aut_time += sw.stop();
auto sp = get_state_players(m);
auto n_s_env = sp.size() - std::accumulate(sp.begin(),
sp.end(),
@ -2055,9 +2072,14 @@ namespace spot
{
n_e_env += sp[e.src];
});
gi.bv->strat2aut_time += sw.stop();
gi.bv->nb_strat_states += n_s_env;
gi.bv->nb_strat_edges += n_e_env;
if (std::tie(gi.bv->max_strat_states, gi.bv->max_strat_edges)
< std::tie(n_s_env, n_e_env))
{
gi.bv->max_strat_states = n_s_env;
gi.bv->max_strat_edges = n_e_env;
}
gi.bv->sum_strat_states += n_s_env;
gi.bv->sum_strat_edges += n_e_env;
}
assert(is_mealy(m));
@ -2383,7 +2405,7 @@ namespace spot
if (bv)
{
auto delta = sw.stop();
bv->trans_time += delta;
bv->sum_trans_time += delta;
if (vs)
*vs << "translating formula done in " << delta
<< " seconds...\n... but it gave a "
@ -2445,7 +2467,7 @@ namespace spot
if (bv)
{
auto delta = sw.stop();
bv->trans_time += delta;
bv->sum_trans_time += delta;
if (vs)
*vs << "translating formula done in " << delta << " seconds\n";
}
@ -2477,7 +2499,7 @@ namespace spot
if (bv)
{
auto delta = sw.stop();
bv->trans_time += delta;
bv->sum_trans_time += delta;
if (vs)
*vs << "translating formula done in " << delta << " seconds\n";
}
@ -2922,10 +2944,10 @@ namespace spot
}
bool res = solve_game(arena);
if (gi.bv)
gi.bv->solve_time += sw.stop();
gi.bv->sum_solve_time += sw.stop();
if (gi.verbose_stream)
*(gi.verbose_stream) << "game solved in "
<< gi.bv->solve_time << " seconds\n";
<< gi.bv->sum_solve_time << " seconds\n";
return res;
}

View file

@ -32,7 +32,7 @@ namespace spot
{
enum class algo
{
DET_SPLIT=0,
DET_SPLIT = 0,
SPLIT_DET,
DPA_SPLIT,
LAR,
@ -42,30 +42,79 @@ namespace spot
enum class splittype
{
AUTO=0, // Uses a heuristic to choose
AUTO = 0, // Uses a heuristic to choose
EXPL, // Explicit enumerations of inputs
SEMISYM, // Works on one bdd per env state
FULLYSYM // Works on a fully symbolic version of the automaton
};
// These statistics are recorded by various steps of the synthesis
// process.
struct bench_var
{
// Number of sub-spefications resulting from the decomposition.
// Updated by ltlsynt.
unsigned sub_specs = 0;
// Total time needed for the synthesis. Computed by ltlsynt.
double total_time = 0.0;
double trans_time = 0.0;
double split_time = 0.0;
double paritize_time = 0.0;
double solve_time = 0.0;
double strat2aut_time = 0.0;
double simplify_strat_time = 0.0;
// Time needed to transform the LTL formula(s) into automata, summed
// over all subspecs. The type of automaton constructed depends on
// the "algo" parameter.
double sum_trans_time = 0.0;
// Time needed to split the automata into separate
// environment/controler steps. Summed over all subspecs.
// Splitting may occur before or after paritization depending on
// the "algo" parameter.
double sum_split_time = 0.0;
// Time needed to convert the automaton to deterministic parity
// automata. Summed over all subspecs. Paritization may occur
// before or after splitting depending on the "algo" parameter.
double sum_paritize_time = 0.0;
// Time needed to solve the game. Summed over all subspecs.
double sum_solve_time = 0.0;
// Time needed to convert the winning strategy into an
// automaton. Summed over all subspecs.
double sum_strat2aut_time = 0.0;
// Time needed to simplify the winning strategy. Summed over
// all subspecs.
double sum_simplify_strat_time = 0.0;
// Time needed to encode all the strategies into one AIG.
double aig_time = 0.0;
unsigned nb_states_arena = 0;
unsigned nb_states_arena_env = 0;
unsigned nb_strat_states = 0;
unsigned nb_strat_edges = 0;
unsigned nb_simpl_strat_states = 0;
unsigned nb_simpl_strat_edges = 0;
unsigned nb_latches = 0;
unsigned nb_gates = 0;
// Size of the automaton resulting from the main translation.
// If multiple subspecifications are used, only the largest
// (states,edges,colors,aps) triplet is kept.
unsigned max_trans_states = 0;
unsigned max_trans_edges = 0;
unsigned max_trans_colors = 0;
unsigned max_trans_ap = 0;
// Size of the game that should be solved. If multiple
// subspecifications are used, only the maximum states and
// colors are kept (those are compared independently).
unsigned max_game_states = 0;
unsigned max_game_colors = 0;
// Size of the strategy extracted from the game. If multiple
// subspecifications are used, only the maximum pair (states,
// edges) is kept.
unsigned max_strat_states = 0;
unsigned max_strat_edges = 0;
// Size of the strategy extracted from the game, summed over all
// subspecifications.
unsigned sum_strat_states = 0;
unsigned sum_strat_edges = 0;
// Size of the strategy after simplification game. If multiple
// subspecifications are used, only the maximum pair (states,
// edges) is kept.
unsigned max_simpl_strat_states = 0;
unsigned max_simpl_strat_edges = 0;
// Size of the strategy after simplification, summed over all
// subspecifications.
unsigned sum_simpl_strat_states = 0;
unsigned sum_simpl_strat_edges = 0;
// Size of the AIG
unsigned aig_latches = 0;
unsigned aig_gates = 0;
// Whether the (global) specification is realizable. Updated by
// ltlsynt.
bool realizable = false;
};