Impove simplify_acceptance

* spot/twaalgos/cleanacc.cc: Use cleanup_acceptance if
propagate_fin_inf was useful.
* spot/twa/acc.hh: Avoid to reverse the order of the condition in
propagate_fin_inf.
* tests/core/accsimpl.test, tests/core/remfin.test,
tests/python/merge.py, tests/python/automata.ipynb: Update tests.
* tests/python/toparity.py: Update tests and add tests to check the
number of states.
This commit is contained in:
Florian Renkin 2020-04-06 14:52:45 +02:00 committed by Alexandre Duret-Lutz
parent a020607664
commit 630b8333fe
7 changed files with 1029 additions and 1139 deletions

View file

@ -471,7 +471,8 @@ namespace spot
{
private:
bool
get_alone_mark(bool& fin, acc_cond::mark_t& mark, bool& conj, acc_code& code)
get_alone_mark(bool& fin, acc_cond::mark_t& mark, bool& conj,
acc_code& code)
{
auto elements = top_conjuncts();
conj = (elements.size() > 1);
@ -510,18 +511,24 @@ namespace spot
auto elements = result.top_disjuncts();
if (elements.size() < 2)
elements = result.top_conjuncts();
result = std::accumulate(elements.begin(), elements.end(), code,
acc_code init_code;
if (conj)
init_code = acc_code::t();
else
init_code = acc_code::f();
bool keeped_code = false;
result = std::accumulate(elements.rbegin(), elements.rend(),
init_code,
[&](acc_code a, acc_code b)
{
if (b != code)
{
b = b.remove(mark, !fin);
if (b != code || keeped_code)
b = b.remove(mark, fin == conj);
if (b == code)
keeped_code = true;
if (conj)
return a & b;
else
return a | b;
}
return a;
});
}
std::vector<acc_code> elements = result.top_disjuncts();
@ -534,7 +541,8 @@ namespace spot
init_code = acc_code::t();
else
init_code = acc_code::f();
result = std::accumulate(elements.begin(), elements.end(), init_code,
result = std::accumulate(elements.rbegin(), elements.rend(),
init_code,
[&](acc_code a, acc_code b)
{
if (conj)

View file

@ -619,8 +619,13 @@ namespace spot
simplify_complementary_marks_here(aut);
fuse_marks_here(aut);
}
aut->set_acceptance(aut->acc().propagate_fin_inf());
cleanup_acceptance_here(aut, true);
auto prop_cond = aut->acc().propagate_fin_inf();
if (prop_cond != aut->acc())
{
aut->set_acceptance(prop_cond);
cleanup_acceptance_here(aut, true);
}
return aut;
}

View file

@ -49,5 +49,5 @@ State: 0
EOF
autfilt --simplify-acceptance 325 > 325s
exp='4 Fin(0) | (Fin(0) & Inf(1)) | (Fin(2) & Inf(3))'
exp='3 Fin(0) | (Fin(1) & Inf(2))'
test "$exp" = "`autfilt --stats='%a %g' 325s`"

View file

@ -336,27 +336,24 @@ State: 3
[!0&!1] 3 {0}
--END--
HOA: v1
States: 4
States: 3
Start: 0
AP: 2 "a" "b"
Acceptance: 4 (Inf(0)&Inf(1)) | Inf(0) | (Inf(2)&Inf(3))
Acceptance: 3 (Inf(1)&Inf(2)) | Inf(0)
properties: trans-labels explicit-labels trans-acc
--BODY--
State: 0
[t] 0 {3}
[0] 1 {3}
[!0] 2 {0 3}
[t] 0 {2}
[0] 1 {2}
[!0] 2 {0 2}
State: 1
[1] 0 {3}
[0&1] 1 {0 3}
[!0&1] 2 {2 3}
[1] 0 {2}
[0&1] 1 {0 2}
[!0&1] 2 {1 2}
State: 2
[!1] 0
[0&!1] 1 {0}
[!0&!1] 2 {0}
[!0&!1] 3
State: 3
[!0&!1] 3 {0 1}
--END--
HOA: v1
States: 1
@ -942,7 +939,7 @@ State: 3
[!0&!1] 3 {0}
--END--
HOA: v1
States: 4
States: 3
Start: 0
AP: 2 "a" "b"
acc-name: Buchi
@ -961,9 +958,6 @@ State: 2
[!1] 0
[0&!1] 1 {0}
[!0&!1] 2 {0}
[!0&!1] 3
State: 3
[!0&!1] 3 {0}
--END--
HOA: v1
States: 1

File diff suppressed because it is too large Load diff

View file

@ -78,7 +78,7 @@ assert hoa == """HOA: v1
States: 3
Start: 0
AP: 2 "a" "b"
Acceptance: 2 Fin(1) | (Inf(0)&Inf(1))
Acceptance: 2 Fin(1) | Inf(0)
properties: trans-labels explicit-labels trans-acc
--BODY--
State: 0

View file

@ -19,6 +19,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import spot
import itertools
# Tests for the new version of to_parity
@ -89,8 +90,9 @@ options = [
]
def test(aut, full=True):
for opt in options:
def test(aut, expected_num_states=[], full=True):
for (opt, expected_num) in\
itertools.zip_longest(options, expected_num_states):
p1 = spot.to_parity(aut,
search_ex = opt.search_ex,
use_last = opt.use_last,
@ -105,6 +107,8 @@ def test(aut, full=True):
pretty_print = opt.pretty_print,
)
assert spot.are_equivalent(aut, p1)
if (expected_num != None):
assert(p1.num_states() == expected_num)
if full:
# Make sure passing opt is the same as setting
# each argument individually
@ -191,7 +195,7 @@ State: 13
[0&1] 5
[!0&!1] 10 {0 1 3 5}
[0&!1] 13 {1 3}
--END--"""))
--END--"""), [35, 28, 23, 30, 29, 25, 22])
test(spot.automaton("""
HOA: v1
@ -209,7 +213,7 @@ State: 1
[0&!1] 1 {4}
[!0&1] 1 {0 1 2 3}
[!0&!1] 1 {0 3}
--END--"""))
--END--"""), [7, 5, 3, 6, 5, 5, 3])
for i,f in enumerate(spot.randltl(10, 400)):
@ -250,7 +254,7 @@ State: 3
[!0&1] 2 {1 4}
[0&1] 3 {0}
--END--
"""))
"""), [80, 22, 80, 80, 80, 17, 10])
test(spot.automaton("""
HOA: v1
@ -284,7 +288,7 @@ State: 4
[0&!1] 4
[0&1] 4 {1 2 4}
--END--
"""))
"""), [9, 6, 6, 6, 7, 6, 6])
test(spot.automaton("""
HOA: v1
@ -306,7 +310,7 @@ State: 1
[0&!1] 1 {2 3}
[0&1] 1 {1 2 4}
--END--
"""))
"""), [11, 6, 3, 7, 7, 4, 3])
# Tests both the old and new version of to_parity
@ -337,8 +341,7 @@ explicit-labels trans-acc --BODY-- State: 0 [0&1] 2 {4 5} [0&1] 4 {0 4}
p = spot.to_parity_old(a, True)
assert p.num_states() == 22
assert spot.are_equivalent(a, p)
test(a)
assert spot.to_parity(a).num_states() == 6
test(a, [8, 7, 8, 8, 6, 7, 6])
for f in spot.randltl(4, 400):
d = spot.translate(f, "det", "G")
@ -354,4 +357,4 @@ for f in spot.randltl(5, 2000):
a = spot.translate('!(GFa -> (GFb & GF(!b & !Xb)))', 'gen', 'det')
b = spot.to_parity_old(a, True)
assert a.equivalent_to(b)
test(a)
test(a, [7, 7, 3, 7, 8, 7, 3])