complete: Fix completion of automata using Fin-acceptance
* src/tgba/acc.cc, src/tgba/acc.hh: Add a way to extract an unstatisfiable mark, and fix the eval() function for Fin acceptance. * src/tgbaalgos/complete.cc: Label the sink state using an unsatisfiable mark. Do not assume generalized Büchi. * src/tgbatest/complete.test: New test. * src/tgbatest/Makefile.am: Add it.
This commit is contained in:
parent
7353e47f0c
commit
23bcbb5b37
5 changed files with 199 additions and 14 deletions
|
|
@ -193,7 +193,7 @@ namespace spot
|
||||||
case acc_cond::acc_op::Inf:
|
case acc_cond::acc_op::Inf:
|
||||||
return (pos[-1].mark & inf) == pos[-1].mark;
|
return (pos[-1].mark & inf) == pos[-1].mark;
|
||||||
case acc_cond::acc_op::Fin:
|
case acc_cond::acc_op::Fin:
|
||||||
return (pos[-1].mark & inf) == 0U;
|
return (pos[-1].mark & inf) != pos[-1].mark;
|
||||||
case acc_cond::acc_op::FinNeg:
|
case acc_cond::acc_op::FinNeg:
|
||||||
case acc_cond::acc_op::InfNeg:
|
case acc_cond::acc_op::InfNeg:
|
||||||
SPOT_UNREACHABLE();
|
SPOT_UNREACHABLE();
|
||||||
|
|
@ -413,6 +413,7 @@ namespace spot
|
||||||
|
|
||||||
bdd_allocator ba;
|
bdd_allocator ba;
|
||||||
int base = ba.allocate_variables(c);
|
int base = ba.allocate_variables(c);
|
||||||
|
assert(base == 0);
|
||||||
std::vector<bdd> r;
|
std::vector<bdd> r;
|
||||||
std::vector<unsigned> sets(c);
|
std::vector<unsigned> sets(c);
|
||||||
for (unsigned i = 0; r.size() < c; ++i)
|
for (unsigned i = 0; r.size() < c; ++i)
|
||||||
|
|
@ -483,6 +484,7 @@ namespace spot
|
||||||
|
|
||||||
bdd_allocator ba;
|
bdd_allocator ba;
|
||||||
int base = ba.allocate_variables(c);
|
int base = ba.allocate_variables(c);
|
||||||
|
assert(base == 0);
|
||||||
std::vector<bdd> r;
|
std::vector<bdd> r;
|
||||||
std::vector<unsigned> sets(c);
|
std::vector<unsigned> sets(c);
|
||||||
for (unsigned i = 0; r.size() < c; ++i)
|
for (unsigned i = 0; r.size() < c; ++i)
|
||||||
|
|
@ -543,6 +545,61 @@ namespace spot
|
||||||
return rescode;
|
return rescode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<bool, acc_cond::mark_t>
|
||||||
|
acc_cond::acc_code::unsat_mark() const
|
||||||
|
{
|
||||||
|
if (empty())
|
||||||
|
return {false, 0U};
|
||||||
|
|
||||||
|
auto used = acc_cond::acc_code::used_sets();
|
||||||
|
unsigned c = used.count();
|
||||||
|
|
||||||
|
bdd_allocator ba;
|
||||||
|
int base = ba.allocate_variables(c);
|
||||||
|
assert(base == 0);
|
||||||
|
std::vector<bdd> r;
|
||||||
|
std::vector<unsigned> sets(c);
|
||||||
|
for (unsigned i = 0; r.size() < c; ++i)
|
||||||
|
{
|
||||||
|
if (used.has(i))
|
||||||
|
{
|
||||||
|
sets[base] = i;
|
||||||
|
r.push_back(bdd_ithvar(base++));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r.push_back(bddfalse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bdd res = to_bdd_rec(&back(), &r[0]);
|
||||||
|
|
||||||
|
if (res == bddtrue)
|
||||||
|
return {false, 0U};
|
||||||
|
if (res == bddfalse)
|
||||||
|
return {true, 0U};
|
||||||
|
|
||||||
|
bdd cube = bdd_satone(!res);
|
||||||
|
mark_t i = 0U;
|
||||||
|
while (cube != bddtrue)
|
||||||
|
{
|
||||||
|
// The acceptance set associated to this BDD variable
|
||||||
|
int s = sets[bdd_var(cube)];
|
||||||
|
|
||||||
|
bdd h = bdd_high(cube);
|
||||||
|
if (h == bddfalse) // Negative variable? -> skip
|
||||||
|
{
|
||||||
|
cube = bdd_low(cube);
|
||||||
|
}
|
||||||
|
else // Positive variable? -> Inf
|
||||||
|
{
|
||||||
|
i.set(s);
|
||||||
|
cube = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {true, i};
|
||||||
|
}
|
||||||
|
|
||||||
bool acc_cond::acc_code::is_dnf() const
|
bool acc_cond::acc_code::is_dnf() const
|
||||||
{
|
{
|
||||||
if (empty() || size() == 2)
|
if (empty() || size() == 2)
|
||||||
|
|
|
||||||
|
|
@ -659,6 +659,10 @@ namespace spot
|
||||||
// Return the set of sets appearing in the condition.
|
// Return the set of sets appearing in the condition.
|
||||||
acc_cond::mark_t used_sets() const;
|
acc_cond::mark_t used_sets() const;
|
||||||
|
|
||||||
|
// Return (true, m) if there exist some m that does not satisfy
|
||||||
|
// the acceptance condition. Return (false, 0U) otherwise.
|
||||||
|
std::pair<bool, acc_cond::mark_t> unsat_mark() const;
|
||||||
|
|
||||||
// Return the sets used as Inf or Fin in the acceptance condition
|
// Return the sets used as Inf or Fin in the acceptance condition
|
||||||
std::pair<acc_cond::mark_t, acc_cond::mark_t> used_inf_fin_sets() const;
|
std::pair<acc_cond::mark_t, acc_cond::mark_t> used_inf_fin_sets() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,21 +25,26 @@ namespace spot
|
||||||
{
|
{
|
||||||
unsigned n = aut->num_states();
|
unsigned n = aut->num_states();
|
||||||
unsigned sink = -1U;
|
unsigned sink = -1U;
|
||||||
acc_cond::mark_t allacc = aut->acc().all_sets();
|
|
||||||
if (allacc == 0U)
|
// UM is a pair (bool, mark). If the Boolean is false, the
|
||||||
|
// acceptance is always satisfiable. Otherwise, MARK is an
|
||||||
|
// example of unsatisfiable mark.
|
||||||
|
auto um = aut->get_acceptance().unsat_mark();
|
||||||
|
if (!um.first)
|
||||||
{
|
{
|
||||||
// We cannot safely complete an automaton if it has no
|
// We cannot safely complete an automaton if its
|
||||||
// acceptance set as the added sink would become accepting.
|
// acceptance is always satisfiable.
|
||||||
// In this case, add an acceptance set to all transitions.
|
auto acc = aut->set_buchi();
|
||||||
allacc = aut->set_buchi();
|
|
||||||
for (auto& t: aut->transition_vector())
|
for (auto& t: aut->transition_vector())
|
||||||
t.acc = allacc;
|
t.acc = acc;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If some acceptance sets were used, loop over the states and
|
// Loop over the states and seek a state that has only self
|
||||||
// seek a state that has only self loops, and that is not
|
// loops, and that is not accepting. This will be our sink
|
||||||
// accepting. This will be our sink state.
|
// state. Note that we do not even have to ensure that the
|
||||||
|
// state is complete as we will complete the whole automaton
|
||||||
|
// in a second pass.
|
||||||
for (unsigned i = 0; i < n; ++i)
|
for (unsigned i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
bool selfloop = true;
|
bool selfloop = true;
|
||||||
|
|
@ -53,8 +58,9 @@ namespace spot
|
||||||
}
|
}
|
||||||
accsum |= t.acc;
|
accsum |= t.acc;
|
||||||
}
|
}
|
||||||
if (selfloop && accsum != allacc) // We have found a sink!
|
if (selfloop && !aut->acc().accepting(accsum))
|
||||||
{
|
{
|
||||||
|
// We have found a sink!
|
||||||
sink = i;
|
sink = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -63,7 +69,7 @@ namespace spot
|
||||||
|
|
||||||
unsigned t = aut->num_transitions();
|
unsigned t = aut->num_transitions();
|
||||||
|
|
||||||
// Now complete all states (including the sink).
|
// Now complete all states (excluding any newly added the sink).
|
||||||
for (unsigned i = 0; i < n; ++i)
|
for (unsigned i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
bdd missingcond = bddtrue;
|
bdd missingcond = bddtrue;
|
||||||
|
|
@ -94,7 +100,7 @@ namespace spot
|
||||||
if (sink == -1U)
|
if (sink == -1U)
|
||||||
{
|
{
|
||||||
sink = aut->new_state();
|
sink = aut->new_state();
|
||||||
++n;
|
aut->new_transition(sink, sink, bddtrue, um.second);
|
||||||
}
|
}
|
||||||
// In case the automaton use state-based acceptance, propagate
|
// In case the automaton use state-based acceptance, propagate
|
||||||
// the acceptance of the first transition to the one we add.
|
// the acceptance of the first transition to the one we add.
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ TESTS = \
|
||||||
det.test \
|
det.test \
|
||||||
neverclaimread.test \
|
neverclaimread.test \
|
||||||
hoaparse.test \
|
hoaparse.test \
|
||||||
|
complete.test \
|
||||||
remfin.test \
|
remfin.test \
|
||||||
dstar.test \
|
dstar.test \
|
||||||
readsave.test \
|
readsave.test \
|
||||||
|
|
|
||||||
117
src/tgbatest/complete.test
Executable file
117
src/tgbatest/complete.test
Executable file
|
|
@ -0,0 +1,117 @@
|
||||||
|
#! /bin/sh
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (C) 2015 Laboratoire de Recherche et Développement de
|
||||||
|
# l'Epita (LRDE).
|
||||||
|
#
|
||||||
|
# This file is part of Spot, a model checking library.
|
||||||
|
#
|
||||||
|
# Spot is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
# License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
. ./defs || exit 1
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cat >automaton <<EOF
|
||||||
|
HOA: v1
|
||||||
|
States: 2
|
||||||
|
Start: 0
|
||||||
|
AP: 1 "a"
|
||||||
|
Acceptance: 1 Fin(0)
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
[0] 1
|
||||||
|
State: 1
|
||||||
|
[0] 1
|
||||||
|
--END--
|
||||||
|
HOA: v1
|
||||||
|
States: 2
|
||||||
|
Start: 0
|
||||||
|
AP: 1 "a"
|
||||||
|
Acceptance: 2 t
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
[0] 1
|
||||||
|
State: 1
|
||||||
|
[0] 1
|
||||||
|
--END--
|
||||||
|
HOA: v1
|
||||||
|
States: 2
|
||||||
|
Start: 0
|
||||||
|
AP: 1 "a"
|
||||||
|
Acceptance: 0 f
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
[0] 1
|
||||||
|
State: 1
|
||||||
|
[0] 1
|
||||||
|
--END--
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >expected <<EOF
|
||||||
|
HOA: v1
|
||||||
|
States: 3
|
||||||
|
Start: 0
|
||||||
|
AP: 1 "a"
|
||||||
|
Acceptance: 1 Fin(0)
|
||||||
|
properties: trans-labels explicit-labels state-acc complete
|
||||||
|
properties: deterministic
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
[0] 1
|
||||||
|
[!0] 2
|
||||||
|
State: 1
|
||||||
|
[0] 1
|
||||||
|
[!0] 2
|
||||||
|
State: 2 {0}
|
||||||
|
[t] 2
|
||||||
|
--END--
|
||||||
|
HOA: v1
|
||||||
|
States: 3
|
||||||
|
Start: 0
|
||||||
|
AP: 1 "a"
|
||||||
|
acc-name: Buchi
|
||||||
|
Acceptance: 1 Inf(0)
|
||||||
|
properties: trans-labels explicit-labels state-acc complete
|
||||||
|
properties: deterministic
|
||||||
|
--BODY--
|
||||||
|
State: 0 {0}
|
||||||
|
[0] 1
|
||||||
|
[!0] 2
|
||||||
|
State: 1 {0}
|
||||||
|
[0] 1
|
||||||
|
[!0] 2
|
||||||
|
State: 2
|
||||||
|
[t] 2
|
||||||
|
--END--
|
||||||
|
HOA: v1
|
||||||
|
States: 2
|
||||||
|
Start: 0
|
||||||
|
AP: 1 "a"
|
||||||
|
Acceptance: 0 f
|
||||||
|
properties: trans-labels explicit-labels state-acc complete
|
||||||
|
properties: deterministic
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
[0] 1
|
||||||
|
[!0] 1
|
||||||
|
State: 1
|
||||||
|
[0] 1
|
||||||
|
[!0] 1
|
||||||
|
--END--
|
||||||
|
EOF
|
||||||
|
|
||||||
|
run 0 ../../bin/autfilt -CH automaton >out
|
||||||
|
cat out
|
||||||
|
diff out expected
|
||||||
Loading…
Add table
Add a link
Reference in a new issue