Commit f3e57901 authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz

simulation: improve merging of transiant-SCCs

* spot/twaalgos/simulation.cc: Code this.
* tests/core/det.test, tests/core/dra2dba.test,
tests/core/satmin.test, tests/core/sim3.test,
tests/python/decompose.ipynb, tests/python/dualize.py: Adjust test
cases.
* NEWS: Mention the optimization.
parent c9ddbd0a
Pipeline #10147 passed with stages
in 154 minutes and 55 seconds
......@@ -45,6 +45,9 @@ New in spot 2.7.5.dev (not yet released)
'ltldo ltl2dstar -f 'GFa -> GFb' | autfilt --small' produces 1
state instead of 4.)
- simulation-based reductions hae learned another trick to better
merge states from transiant SCCs.
- acc_cond::top_disjuncts() and acc_cond::top_conjuncts() can be
used to split an acceptance condition on the top-level & or |.
These methods also exist in acc_cond::acc_code.
......
......@@ -23,6 +23,7 @@
#include <utility>
#include <cmath>
#include <limits>
#include <numeric>
#include <spot/twaalgos/simulation.hh>
#include <spot/misc/minato.hh>
#include <spot/twa/bddprint.hh>
......@@ -493,7 +494,7 @@ namespace spot
}
}
// Build the minimal resulting automaton.
// Build the simplified automaton.
twa_graph_ptr build_result()
{
twa_graph_ptr res = make_twa_graph(a_->get_dict());
......@@ -526,6 +527,9 @@ namespace spot
(*record_implications_)[s] = relation_[cl];
}
std::vector<bdd> signatures;
signatures.reserve(sorted_classes_.size());
// Acceptance of states. Only used if Sba && Cosimulation.
std::vector<acc_cond::mark_t> accst;
if (Sba && Cosimulation)
......@@ -538,6 +542,7 @@ namespace spot
unsigned nb_minato = 0;
auto all_inf = all_inf_;
unsigned srcst = 0;
// For each class, we will create
// all the edges between the states.
for (auto& p: sorted_classes_)
......@@ -552,7 +557,11 @@ namespace spot
if (Cosimulation)
sig = bdd_compose(sig, bddfalse, bdd_var(bdd_initial));
// Get all the variable in the signature.
assert(gb->get_state(src.id()) == srcst);
assert(signatures.size() == srcst);
signatures.push_back(bdd_exist(sig, all_proms_));
// Get all the variables in the signature.
bdd sup_sig = bdd_support(sig);
// Get the variable in the signature which represents the
......@@ -607,7 +616,6 @@ namespace spot
// acceptance conditions on the input automaton,
// we must revert them to create a new edge.
acc ^= all_inf;
if (Cosimulation)
{
if (Sba)
......@@ -617,7 +625,7 @@ namespace spot
// to all edges leaving src. As we
// can't do this here, store this in a table
// so we can fix it later.
accst[gb->get_state(src.id())] = acc;
accst[srcst] = acc;
acc = {};
}
gb->new_edge(dst.id(), src.id(), cond, acc);
......@@ -628,6 +636,7 @@ namespace spot
}
}
}
++srcst;
}
res->set_init_state(gb->get_state(previous_class_
......@@ -652,6 +661,41 @@ namespace spot
}
}
// Attempt to merge trivial SCCs
if (!record_implications_ && res->num_states() > 1)
{
scc_info si(res, scc_info_options::NONE);
unsigned nscc = si.scc_count();
unsigned nstates = res->num_states();
std::vector<unsigned> redirect(nstates);
std::iota(redirect.begin(), redirect.end(), 0);
bool changed = false;
for (unsigned scc = 0; scc < nscc; ++scc)
if (si.is_trivial(scc))
{
unsigned s = si.one_state_of(scc);
bdd ref = signatures[s];
for (unsigned i = 0; i < nstates; ++i)
if (si.reachable_state(i)
&& signatures[i] == ref && !si.is_trivial(si.scc_of(i)))
{
changed = true;
redirect[s] = i;
break;
}
}
if (changed)
{
if (Cosimulation)
for (auto& e: res->edges())
e.src = redirect[e.src];
else
for (auto& e: res->edges())
e.dst = redirect[e.dst];
res->set_init_state(redirect[res->get_init_state_number()]);
}
}
// If we recorded implications for the determinization
// procedure, we should not remove unreachable states, as that
// will invalidate the contents of the IMPLICATIONS vector.
......
#!/bin/sh
# -*- coding: utf-8 -*-
# Copyright (C) 2013-2018 Laboratoire de Recherche et Développement de
# Copyright (C) 2013-2019 Laboratoire de Recherche et Développement de
# l'Epita (LRDE).
#
# This file is part of Spot, a model checking library.
......@@ -24,17 +24,17 @@ set -e
cat >formulas <<'EOF'
1,13,X((a M F((!b & !c) | (b & c))) W (G!c U b))
1,5,X(((a & b) R (!a U !c)) R b)
1,9,XXG(Fa U Xb)
1,8,XXG(Fa U Xb)
1,5,(!a M !b) W F!c
1,3,(b & Fa & GFc) R a
1,2,(a R (b W a)) W G(!a M (b | c))
1,11,(Fa W b) R (!a | Fc)
1,7,X(G(!a M !b) | G(a | G!a))
1,6,X(G(!a M !b) | G(a | G!a))
1,2,Fa W Gb
1,3,Ga | GFb
1,2,Ga | GFb
1,9,G((G!a & ((!b & X!c) | (b & Xc))) | (Fa & ((!b & Xc) | (b & X!c))))
1,5,a M G(F!b | X!a)
1,4,G!a R XFb
1,3,G!a R XFb
1,4,XF(!a | GFb)
1,5,X(GF!a U a)
1,5,(a | G(a M !b)) W Fc
......@@ -43,14 +43,14 @@ cat >formulas <<'EOF'
1,2,XG!a R Fb
1,4,GFc | (a & Fb)
1,6,X(a R (Fb R F!b))
1,2,G(Xa M Fa)
1,4,X(Gb | GFa)
1,1,G(Xa M Fa)
1,3,X(Gb | GFa)
1,9,X(Gc | XG((b & Ga) | (!b & F!a)))
1,2,Ga R Fb
1,3,G(a U (b | X((!a & !c) | (a & c))))
1,5,XG((G!a & F!b) | (Fa & (a | Gb)))
1,9,(a U X!a) | XG(!b & Fc)
1,4,X(G!a | GFa)
1,7,(a U X!a) | XG(!b & Fc)
1,3,X(G!a | GFa)
1,4,G(G!a | F!c | G!b)
EOF
......
......@@ -330,4 +330,5 @@ Acc-Sig: +2
EOF
autcross 'dstar2tgba -D' --language-preserved -F in.dra --csv=out.csv
grep '3,18,107,144,1,2,0,0,0$' out.csv
cat out.csv
grep '3,17,104,136,1,1,0,0,0$' out.csv
#!/bin/sh
# -*- coding: utf-8 -*-
# Copyright (C) 2013, 2017, 2018 Laboratoire de Recherche et Développement
# Copyright (C) 2013, 2017, 2018, 2019 Laboratoire de Recherche et Développement
# de l'Epita (LRDE).
#
# This file is part of Spot, a model checking library.
......@@ -949,7 +949,7 @@ cat >expected <<'EOF'
"!(((p0) R ((p1) W (p0))) W (G((!(p0)) M ((p1) | (p2)))))","16",4
"!(((p0) R ((p1) W (p0))) W (G((!(p0)) M ((p1) | (p2)))))","17",4
"X((G((!(p0)) M (!(p1)))) | (G((p0) | (G(!(p0))))))","1",5
"X((G((!(p0)) M (!(p1)))) | (G((p0) | (G(!(p0))))))","2",7
"X((G((!(p0)) M (!(p1)))) | (G((p0) | (G(!(p0))))))","2",6
"X((G((!(p0)) M (!(p1)))) | (G((p0) | (G(!(p0))))))","3",6
"X((G((!(p0)) M (!(p1)))) | (G((p0) | (G(!(p0))))))","4",6
"X((G((!(p0)) M (!(p1)))) | (G((p0) | (G(!(p0))))))","6",6
......@@ -1013,7 +1013,7 @@ cat >expected <<'EOF'
"!((F(p0)) W (G(p1)))","16",2
"!((F(p0)) W (G(p1)))","17",2
"(G(F(p1))) | (G(p0))","1",3
"(G(F(p1))) | (G(p0))","2",3
"(G(F(p1))) | (G(p0))","2",2
"(G(F(p1))) | (G(p0))","3",2
"(G(F(p1))) | (G(p0))","4",2
"(G(F(p1))) | (G(p0))","6",2
......@@ -1076,8 +1076,8 @@ cat >expected <<'EOF'
"!((p0) M (G((F(!(p1))) | (X(!(p0))))))","15",4
"!((p0) M (G((F(!(p1))) | (X(!(p0))))))","16",4
"!((p0) M (G((F(!(p1))) | (X(!(p0))))))","17",4
"(G(!(p0))) R (X(F(p1)))","1",4
"(G(!(p0))) R (X(F(p1)))","2",4
"(G(!(p0))) R (X(F(p1)))","1",3
"(G(!(p0))) R (X(F(p1)))","2",3
"(G(!(p0))) R (X(F(p1)))","3",3
"(G(!(p0))) R (X(F(p1)))","4",3
"(G(!(p0))) R (X(F(p1)))","6",3
......@@ -1333,7 +1333,7 @@ cat >expected <<'EOF'
"!(X((p0) R ((F(p1)) R (F(!(p1))))))","16",3
"!(X((p0) R ((F(p1)) R (F(!(p1))))))","17",3
"G((X(p0)) M (F(p0)))","1",2
"G((X(p0)) M (F(p0)))","2",2
"G((X(p0)) M (F(p0)))","2",1
"G((X(p0)) M (F(p0)))","3",1
"G((X(p0)) M (F(p0)))","4",1
"G((X(p0)) M (F(p0)))","6",1
......@@ -1365,7 +1365,7 @@ cat >expected <<'EOF'
"!(G((X(p0)) M (F(p0))))","16",2
"!(G((X(p0)) M (F(p0))))","17",2
"X((G(F(p1))) | (G(p0)))","1",4
"X((G(F(p1))) | (G(p0)))","2",4
"X((G(F(p1))) | (G(p0)))","2",3
"X((G(F(p1))) | (G(p0)))","3",3
"X((G(F(p1))) | (G(p0)))","4",3
"X((G(F(p1))) | (G(p0)))","6",3
......@@ -1493,7 +1493,7 @@ cat >expected <<'EOF'
"!(X(G(((G(!(p0))) & (F(!(p1)))) | ((F(p0)) & ((p0) | (G(p1)))))))","16",7
"!(X(G(((G(!(p0))) & (F(!(p1)))) | ((F(p0)) & ((p0) | (G(p1)))))))","17",7
"X((G(F(p0))) | (G(!(p0))))","1",4
"X((G(F(p0))) | (G(!(p0))))","2",4
"X((G(F(p0))) | (G(!(p0))))","2",3
"X((G(F(p0))) | (G(!(p0))))","3",3
"X((G(F(p0))) | (G(!(p0))))","4",3
"X((G(F(p0))) | (G(!(p0))))","6",3
......
......@@ -47,7 +47,7 @@ State: 6 {0 3}
--END--
EOF
test "`autfilt --small input --stats=%S,%s`" = 7,2
test "`autfilt --small input --stats=%S,%s`" = 7,1
autfilt -S --high --small input -H > out
cat >expected <<EOF
......
This diff is collapsed.
#!/usr/bin/python3
# -*- mode: python; coding: utf-8 -*-
# Copyright (C) 2017, 2018 Laboratoire de Recherche et Développement de
# Copyright (C) 2017-2019 Laboratoire de Recherche et Développement de
# l'EPITA.
#
# This file is part of Spot, a model checking library.
......@@ -553,7 +553,7 @@ dual = spot.dualize(aut)
h = dual.to_str('hoa')
assert h == """HOA: v1
States: 6
States: 5
Start: 0
AP: 2 "a" "b"
acc-name: co-Buchi
......@@ -561,27 +561,24 @@ Acceptance: 1 Fin(0)
properties: trans-labels explicit-labels state-acc complete
properties: deterministic univ-branch
--BODY--
State: 0
[0] 1
[!0] 1&2
State: 1 {0}
[0&1] 1
[0&!1] 4
[!0&!1] 2&4
[!0&1] 1&2
State: 0 {0}
[0&1] 0
[0&!1] 1
[!0&!1] 1&2
[!0&1] 0&2
State: 1
[0&1] 0
[0&!1] 1
[!0&!1] 1&2
[!0&1] 0&2
State: 2
[!0&1] 3
[0 | !1] 5
[0 | !1] 4
State: 3 {0}
[!0] 3
[0] 5
[0] 4
State: 4
[0&1] 1
[0&!1] 4
[!0&!1] 2&4
[!0&1] 1&2
State: 5
[t] 5
[t] 4
--END--"""
opts = spot.option_map()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment