dtgbasat: add a colored option
This was suggested by one of the reviewers of our LPAR'15 paper. * src/twaalgos/dtgbasat.cc, src/twaalgos/dtgbasat.hh: Implement the colored option. * src/tests/satmin2.test: Test it. * doc/org/satmin.org, NEWS: Document it.
This commit is contained in:
parent
6b3de8afa0
commit
3378d72a88
5 changed files with 169 additions and 21 deletions
5
NEWS
5
NEWS
|
|
@ -1,6 +1,9 @@
|
||||||
New in spot 1.99.3a (not yet released)
|
New in spot 1.99.3a (not yet released)
|
||||||
|
|
||||||
Nothing yet.
|
* autfilt's --sat-minimize now takes a "colored" option to constrain
|
||||||
|
all transitions (or states) in the output automaton to belong to
|
||||||
|
exactly one acceptance sets. This is useful when targeting parity
|
||||||
|
acceptance.
|
||||||
|
|
||||||
New in spot 1.99.3 (2015-08-26)
|
New in spot 1.99.3 (2015-08-26)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,10 @@ Let us first state a few facts about this minimization procedure.
|
||||||
to the SAT solver) exceeds $2^{31}$, or when the SAT-solver was
|
to the SAT solver) exceeds $2^{31}$, or when the SAT-solver was
|
||||||
killed by a signal. [[file:autfilt.org][=autfilt --sat-minimize=]] will only output an
|
killed by a signal. [[file:autfilt.org][=autfilt --sat-minimize=]] will only output an
|
||||||
automaton if the SAT-based minimization was successful.
|
automaton if the SAT-based minimization was successful.
|
||||||
6) Our [[https://www.lrde.epita.fr/~adl/dl/adl/baarir.14.forte.pdf%0A][FORTE'14 paper]] describes the SAT encoding for the minimization
|
6) Our [[https://www.lrde.epita.fr/~adl/dl/adl/baarir.14.forte.pdf][FORTE'14 paper]] describes the SAT encoding for the minimization
|
||||||
of deterministic BA and TGBA. Since then, the technique used in
|
of deterministic BA and TGBA. Our [[https://www.lrde.epita.fr/~adl/dl/adl/baarir.15.lpar.pdf][LPAR'15 paper]] describes the
|
||||||
the SAT encoding for deterministic TGBA has been generalized to
|
generalization of the SAT encoding to deal with deterministic TωA
|
||||||
deal with any deterministic TωA.
|
with any acceptance condition.
|
||||||
|
|
||||||
* How to change the SAT solver used
|
* How to change the SAT solver used
|
||||||
|
|
||||||
|
|
@ -672,6 +672,91 @@ that can be any of the following:
|
||||||
- =dichotomy= :: instead of looking for a smaller automaton starting
|
- =dichotomy= :: instead of looking for a smaller automaton starting
|
||||||
from =N=, and then checking =N-1=, =N-2=, etc., do a binary
|
from =N=, and then checking =N-1=, =N-2=, etc., do a binary
|
||||||
search starting from =N/2=.
|
search starting from =N/2=.
|
||||||
|
- =colored= :: force all transitions (or all states if =-S= is used)
|
||||||
|
to belong to exactly one acceptance condition.
|
||||||
|
|
||||||
|
|
||||||
|
The =colored= option is useful when used in conjunction with a parity
|
||||||
|
acceptance condition. Indeed, the parity acceptance condition by
|
||||||
|
itself does not require that the acceptance sets form a partition of
|
||||||
|
the automaton (which is expected from parity automata).
|
||||||
|
|
||||||
|
Compare the following, where parity acceptance is used, but the
|
||||||
|
automaton is not colored:
|
||||||
|
|
||||||
|
#+NAME: autfiltsm9
|
||||||
|
#+BEGIN_SRC sh :results verbatim :exports code
|
||||||
|
autfilt -S --sat-minimize='acc="parity max even 3"' output2.hoa --dot=.a
|
||||||
|
#+END_SRC
|
||||||
|
#+RESULTS: autfiltsm9
|
||||||
|
#+begin_example
|
||||||
|
digraph G {
|
||||||
|
rankdir=LR
|
||||||
|
label=<Inf(<font color="#FAA43A">❷</font>) | (Fin(<font color="#F17CB0">❶</font>) & Inf(<font color="#5DA5DA">⓿</font>))>
|
||||||
|
labelloc="t"
|
||||||
|
node [shape="circle"]
|
||||||
|
fontname="Lato"
|
||||||
|
node [fontname="Lato"]
|
||||||
|
edge [fontname="Lato"]
|
||||||
|
node[style=filled, fillcolor="#ffffa0"] edge[arrowhead=vee, arrowsize=.7]
|
||||||
|
I [label="", style=invis, width=0]
|
||||||
|
I -> 0
|
||||||
|
0 [label=<0>]
|
||||||
|
0 -> 0 [label=<!a>]
|
||||||
|
0 -> 1 [label=<a & !b>]
|
||||||
|
0 -> 2 [label=<a & b>]
|
||||||
|
1 [label=<1>]
|
||||||
|
1 -> 1 [label=<!b>]
|
||||||
|
1 -> 2 [label=<b>]
|
||||||
|
2 [label=<2<br/><font color="#5DA5DA">⓿</font>>]
|
||||||
|
2 -> 0 [label=<1>]
|
||||||
|
}
|
||||||
|
#+end_example
|
||||||
|
|
||||||
|
#+BEGIN_SRC dot :file autfiltsm9.png :cmdline -Tpng :var txt=autfiltsm9 :exports results
|
||||||
|
$txt
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
[[file:autfiltsm9.png]]
|
||||||
|
|
||||||
|
... to the following, where the automaton is colored, i.e., each state
|
||||||
|
belong to exactly one acceptance set:
|
||||||
|
|
||||||
|
#+NAME: autfiltsm10
|
||||||
|
#+BEGIN_SRC sh :results verbatim :exports code
|
||||||
|
autfilt -S --sat-minimize='acc="parity max even 3",colored' output2.hoa --dot=.a
|
||||||
|
#+END_SRC
|
||||||
|
#+RESULTS: autfiltsm10
|
||||||
|
#+begin_example
|
||||||
|
digraph G {
|
||||||
|
rankdir=LR
|
||||||
|
label=<Inf(<font color="#FAA43A">❷</font>) | (Fin(<font color="#F17CB0">❶</font>) & Inf(<font color="#5DA5DA">⓿</font>))>
|
||||||
|
labelloc="t"
|
||||||
|
node [shape="circle"]
|
||||||
|
fontname="Lato"
|
||||||
|
node [fontname="Lato"]
|
||||||
|
edge [fontname="Lato"]
|
||||||
|
node[style=filled, fillcolor="#ffffa0"] edge[arrowhead=vee, arrowsize=.7]
|
||||||
|
I [label="", style=invis, width=0]
|
||||||
|
I -> 0
|
||||||
|
0 [label=<0<br/><font color="#F17CB0">❶</font>>]
|
||||||
|
0 -> 0 [label=<!b>]
|
||||||
|
0 -> 1 [label=<b>]
|
||||||
|
1 [label=<1<br/><font color="#F17CB0">❶</font>>]
|
||||||
|
1 -> 1 [label=<!a>]
|
||||||
|
1 -> 2 [label=<a>]
|
||||||
|
2 [label=<2<br/><font color="#FAA43A">❷</font>>]
|
||||||
|
2 -> 0 [label=<1>]
|
||||||
|
}
|
||||||
|
#+end_example
|
||||||
|
|
||||||
|
#+BEGIN_SRC dot :file autfiltsm10.png :cmdline -Tpng :var txt=autfiltsm10 :exports results
|
||||||
|
$txt
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
[[file:autfiltsm10.png]]
|
||||||
|
|
||||||
* Logging statistics
|
* Logging statistics
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,15 @@ $autfilt -S --sat-minimize='acc="Fin(0)|Inf(1)"' test.hoa \
|
||||||
--stats=%s > output
|
--stats=%s > output
|
||||||
test `cat output` = 3
|
test `cat output` = 3
|
||||||
|
|
||||||
|
# How about a state-based DPA?
|
||||||
|
$autfilt -S --sat-minimize='acc="parity max even 3",colored' -H test.hoa \
|
||||||
|
> output
|
||||||
|
cat output
|
||||||
|
grep 'properties:.*colored' output
|
||||||
|
grep 'States: 3' output
|
||||||
|
grep 'acc-name: parity max even 3' output
|
||||||
|
grep 'Acceptance: 3 Inf(2) | (Fin(1) & Inf(0))' output
|
||||||
|
test 3 = `grep -c 'State: [012] {[012]}' output`
|
||||||
|
|
||||||
# I get headaches whenever I think about this acceptance condition, so
|
# I get headaches whenever I think about this acceptance condition, so
|
||||||
# it should be a good test case.
|
# it should be a good test case.
|
||||||
|
|
|
||||||
|
|
@ -604,7 +604,7 @@ namespace spot
|
||||||
|
|
||||||
static
|
static
|
||||||
sat_stats dtgba_to_sat(std::ostream& out, const_twa_graph_ptr ref,
|
sat_stats dtgba_to_sat(std::ostream& out, const_twa_graph_ptr ref,
|
||||||
dict& d, bool state_based)
|
dict& d, bool state_based, bool colored)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
debug_dict = ref->get_dict();
|
debug_dict = ref->get_dict();
|
||||||
|
|
@ -714,6 +714,45 @@ namespace spot
|
||||||
++nclauses;
|
++nclauses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (colored)
|
||||||
|
{
|
||||||
|
unsigned nacc = d.cand_nacc;
|
||||||
|
dout << "transitions belong to exactly one of the "
|
||||||
|
<< nacc << " acceptance set\n";
|
||||||
|
bdd all = bddtrue;
|
||||||
|
while (all != bddfalse)
|
||||||
|
{
|
||||||
|
bdd l = bdd_satoneset(all, ap, bddfalse);
|
||||||
|
all -= l;
|
||||||
|
for (unsigned q1 = 0; q1 < d.cand_size; ++q1)
|
||||||
|
for (unsigned q2 = 0; q2 < d.cand_size; ++q2)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < nacc; ++i)
|
||||||
|
{
|
||||||
|
transition_acc ti(q1, l, {i}, q2);
|
||||||
|
int tai = d.transaccid[ti];
|
||||||
|
|
||||||
|
for (unsigned j = 0; j < nacc; ++j)
|
||||||
|
if (i != j)
|
||||||
|
{
|
||||||
|
transition_acc tj(q1, l, {j}, q2);
|
||||||
|
int taj = d.transaccid[tj];
|
||||||
|
out << -tai << ' ' << -taj << " 0\n";
|
||||||
|
++nclauses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < nacc; ++i)
|
||||||
|
{
|
||||||
|
transition_acc ti(q1, l, {i}, q2);
|
||||||
|
int tai = d.transaccid[ti];
|
||||||
|
out << tai << ' ';
|
||||||
|
}
|
||||||
|
out << "0\n";
|
||||||
|
++nclauses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!d.all_silly_cand_acc.empty())
|
if (!d.all_silly_cand_acc.empty())
|
||||||
{
|
{
|
||||||
dout << "no transition with silly acceptance\n";
|
dout << "no transition with silly acceptance\n";
|
||||||
|
|
@ -1084,7 +1123,8 @@ namespace spot
|
||||||
dtgba_sat_synthetize(const const_twa_graph_ptr& a,
|
dtgba_sat_synthetize(const const_twa_graph_ptr& a,
|
||||||
unsigned target_acc_number,
|
unsigned target_acc_number,
|
||||||
const acc_cond::acc_code& target_acc,
|
const acc_cond::acc_code& target_acc,
|
||||||
int target_state_number, bool state_based)
|
int target_state_number,
|
||||||
|
bool state_based, bool colored)
|
||||||
{
|
{
|
||||||
if (target_state_number == 0)
|
if (target_state_number == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -1103,7 +1143,7 @@ namespace spot
|
||||||
|
|
||||||
timer_map t;
|
timer_map t;
|
||||||
t.start("encode");
|
t.start("encode");
|
||||||
sat_stats s = dtgba_to_sat(solver(), a, d, state_based);
|
sat_stats s = dtgba_to_sat(solver(), a, d, state_based, colored);
|
||||||
t.stop("encode");
|
t.stop("encode");
|
||||||
t.start("solve");
|
t.start("solve");
|
||||||
solution = solver.get_solution();
|
solution = solver.get_solution();
|
||||||
|
|
@ -1156,8 +1196,8 @@ namespace spot
|
||||||
dtgba_sat_minimize(const const_twa_graph_ptr& a,
|
dtgba_sat_minimize(const const_twa_graph_ptr& a,
|
||||||
unsigned target_acc_number,
|
unsigned target_acc_number,
|
||||||
const acc_cond::acc_code& target_acc,
|
const acc_cond::acc_code& target_acc,
|
||||||
bool state_based,
|
bool state_based, int max_states,
|
||||||
int max_states)
|
bool colored)
|
||||||
{
|
{
|
||||||
int n_states = (max_states < 0) ?
|
int n_states = (max_states < 0) ?
|
||||||
stats_reachable(a).states : max_states + 1;
|
stats_reachable(a).states : max_states + 1;
|
||||||
|
|
@ -1167,7 +1207,8 @@ namespace spot
|
||||||
{
|
{
|
||||||
auto next =
|
auto next =
|
||||||
dtgba_sat_synthetize(prev ? prev : a, target_acc_number,
|
dtgba_sat_synthetize(prev ? prev : a, target_acc_number,
|
||||||
target_acc, --n_states, state_based);
|
target_acc, --n_states,
|
||||||
|
state_based, colored);
|
||||||
if (!next)
|
if (!next)
|
||||||
return prev;
|
return prev;
|
||||||
else
|
else
|
||||||
|
|
@ -1181,8 +1222,8 @@ namespace spot
|
||||||
dtgba_sat_minimize_dichotomy(const const_twa_graph_ptr& a,
|
dtgba_sat_minimize_dichotomy(const const_twa_graph_ptr& a,
|
||||||
unsigned target_acc_number,
|
unsigned target_acc_number,
|
||||||
const acc_cond::acc_code& target_acc,
|
const acc_cond::acc_code& target_acc,
|
||||||
bool state_based,
|
bool state_based, int max_states,
|
||||||
int max_states)
|
bool colored)
|
||||||
{
|
{
|
||||||
if (max_states < 1)
|
if (max_states < 1)
|
||||||
max_states = stats_reachable(a).states - 1;
|
max_states = stats_reachable(a).states - 1;
|
||||||
|
|
@ -1194,7 +1235,8 @@ namespace spot
|
||||||
int target = (max_states + min_states) / 2;
|
int target = (max_states + min_states) / 2;
|
||||||
auto next =
|
auto next =
|
||||||
dtgba_sat_synthetize(prev ? prev : a, target_acc_number,
|
dtgba_sat_synthetize(prev ? prev : a, target_acc_number,
|
||||||
target_acc, target, state_based);
|
target_acc, target, state_based,
|
||||||
|
colored);
|
||||||
if (!next)
|
if (!next)
|
||||||
{
|
{
|
||||||
min_states = target + 1;
|
min_states = target + 1;
|
||||||
|
|
@ -1228,6 +1270,7 @@ namespace spot
|
||||||
int states = om.get("states", -1);
|
int states = om.get("states", -1);
|
||||||
int max_states = om.get("max-states", -1);
|
int max_states = om.get("max-states", -1);
|
||||||
auto accstr = om.get_str("acc");
|
auto accstr = om.get_str("acc");
|
||||||
|
bool colored = om.get("colored", 0);
|
||||||
|
|
||||||
// Assume we are going to use the input automaton acceptance...
|
// Assume we are going to use the input automaton acceptance...
|
||||||
bool user_supplied_acc = false;
|
bool user_supplied_acc = false;
|
||||||
|
|
@ -1316,9 +1359,9 @@ namespace spot
|
||||||
if (states == -1)
|
if (states == -1)
|
||||||
{
|
{
|
||||||
auto orig = a;
|
auto orig = a;
|
||||||
if (!target_is_buchi || !a->acc().is_buchi())
|
if (!target_is_buchi || !a->acc().is_buchi() || colored)
|
||||||
a = (dicho ? dtgba_sat_minimize_dichotomy : dtgba_sat_minimize)
|
a = (dicho ? dtgba_sat_minimize_dichotomy : dtgba_sat_minimize)
|
||||||
(a, nacc, target_acc, state_based, max_states);
|
(a, nacc, target_acc, state_based, max_states, colored);
|
||||||
else
|
else
|
||||||
a = (dicho ? dtba_sat_minimize_dichotomy : dtba_sat_minimize)
|
a = (dicho ? dtba_sat_minimize_dichotomy : dtba_sat_minimize)
|
||||||
(a, state_based, max_states);
|
(a, state_based, max_states);
|
||||||
|
|
@ -1328,8 +1371,9 @@ namespace spot
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!target_is_buchi || !a->acc().is_buchi())
|
if (!target_is_buchi || !a->acc().is_buchi() || colored)
|
||||||
a = dtgba_sat_synthetize(a, nacc, target_acc, states, state_based);
|
a = dtgba_sat_synthetize(a, nacc, target_acc, states,
|
||||||
|
state_based, colored);
|
||||||
else
|
else
|
||||||
a = dtba_sat_synthetize(a, states, state_based);
|
a = dtba_sat_synthetize(a, states, state_based);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,9 @@ namespace spot
|
||||||
/// of a state to share the same acceptance conditions, effectively
|
/// of a state to share the same acceptance conditions, effectively
|
||||||
/// turning the TGBA into a TBA.
|
/// turning the TGBA into a TBA.
|
||||||
///
|
///
|
||||||
|
/// \param colored if true, force all transitions to belong to
|
||||||
|
/// exactly one acceptance set.
|
||||||
|
///
|
||||||
/// This functions attempts to find a TGBA with \a target_acc_number
|
/// This functions attempts to find a TGBA with \a target_acc_number
|
||||||
/// acceptance sets and target_state_number states that is
|
/// acceptance sets and target_state_number states that is
|
||||||
/// equivalent to \a a. If no such TGBA is found, a null pointer is
|
/// equivalent to \a a. If no such TGBA is found, a null pointer is
|
||||||
|
|
@ -50,7 +53,8 @@ namespace spot
|
||||||
unsigned target_acc_number,
|
unsigned target_acc_number,
|
||||||
const acc_cond::acc_code& target_acc,
|
const acc_cond::acc_code& target_acc,
|
||||||
int target_state_number,
|
int target_state_number,
|
||||||
bool state_based = false);
|
bool state_based = false,
|
||||||
|
bool colored = false);
|
||||||
|
|
||||||
/// \brief Attempt to minimize a deterministic TGBA with a SAT solver.
|
/// \brief Attempt to minimize a deterministic TGBA with a SAT solver.
|
||||||
///
|
///
|
||||||
|
|
@ -63,7 +67,8 @@ namespace spot
|
||||||
unsigned target_acc_number,
|
unsigned target_acc_number,
|
||||||
const acc_cond::acc_code& target_acc,
|
const acc_cond::acc_code& target_acc,
|
||||||
bool state_based = false,
|
bool state_based = false,
|
||||||
int max_states = -1);
|
int max_states = -1,
|
||||||
|
bool colored = false);
|
||||||
|
|
||||||
/// \brief Attempt to minimize a deterministic TGBA with a SAT solver.
|
/// \brief Attempt to minimize a deterministic TGBA with a SAT solver.
|
||||||
///
|
///
|
||||||
|
|
@ -76,7 +81,8 @@ namespace spot
|
||||||
unsigned target_acc_number,
|
unsigned target_acc_number,
|
||||||
const acc_cond::acc_code& target_acc,
|
const acc_cond::acc_code& target_acc,
|
||||||
bool state_based = false,
|
bool state_based = false,
|
||||||
int max_states = -1);
|
int max_states = -1,
|
||||||
|
bool colored = false);
|
||||||
|
|
||||||
/// \brief High-level interface to SAT-based minimization
|
/// \brief High-level interface to SAT-based minimization
|
||||||
///
|
///
|
||||||
|
|
@ -90,6 +96,7 @@ namespace spot
|
||||||
/// acc = "Rabin 3"
|
/// acc = "Rabin 3"
|
||||||
/// acc = "same" /* default */
|
/// acc = "same" /* default */
|
||||||
/// dichotomy = 1 // use dichotomy instead of decreasing loop
|
/// dichotomy = 1 // use dichotomy instead of decreasing loop
|
||||||
|
/// colored = 1 // build a colored TωA
|
||||||
///
|
///
|
||||||
SPOT_API twa_graph_ptr
|
SPOT_API twa_graph_ptr
|
||||||
sat_minimize(twa_graph_ptr aut, const char* opt, bool state_based = false);
|
sat_minimize(twa_graph_ptr aut, const char* opt, bool state_based = false);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue