dstarparse: get rid of the deticated data structures and conversions
* src/dstarparse/dstarparse.yy: Use the twa_graph_ptr to store the acceptance condition. * src/dstarparse/dra2ba.cc, src/dstarparse/dstar2tgba.cc, src/dstarparse/nra2nba.cc, src/dstarparse/nsa2tgba.cc: Delete all these conversion routines. * src/dstarparse/public.hh, src/dstarparse/Makefile.am: Adjust. * src/bin/dstar2tgba.cc: Adjust to call to_generalized_buchi() instead. * src/bin/ltlcross.cc: Adjust to call remove_fin() instead. * src/bin/ltldo.cc: Use the parsed automaton as-is. * src/tests/degenid.test, src/tests/dstar.test, src/tests/ikwiad.cc: Adjust test cases.
This commit is contained in:
parent
5f0b6dc36c
commit
9b5340b90a
13 changed files with 75 additions and 874 deletions
|
|
@ -37,6 +37,7 @@
|
||||||
#include "twaalgos/hoa.hh"
|
#include "twaalgos/hoa.hh"
|
||||||
#include "twaalgos/neverclaim.hh"
|
#include "twaalgos/neverclaim.hh"
|
||||||
#include "twaalgos/stats.hh"
|
#include "twaalgos/stats.hh"
|
||||||
|
#include "twaalgos/totgba.hh"
|
||||||
#include "twa/bddprint.hh"
|
#include "twa/bddprint.hh"
|
||||||
#include "misc/optionmap.hh"
|
#include "misc/optionmap.hh"
|
||||||
#include "misc/timer.hh"
|
#include "misc/timer.hh"
|
||||||
|
|
@ -290,7 +291,7 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has('A'))
|
if (has('A'))
|
||||||
daut_acc_ = daut->accpair_count;
|
daut_acc_ = daut->aut->num_sets() / 2;
|
||||||
|
|
||||||
if (has('C'))
|
if (has('C'))
|
||||||
daut_scc_ = spot::scc_info(daut->aut).scc_count();
|
daut_scc_ = spot::scc_info(daut->aut).scc_count();
|
||||||
|
|
@ -355,7 +356,7 @@ namespace
|
||||||
|
|
||||||
spot::stopwatch sw;
|
spot::stopwatch sw;
|
||||||
sw.start();
|
sw.start();
|
||||||
auto nba = spot::dstar_to_tgba(daut);
|
auto nba = spot::to_generalized_buchi(daut->aut);
|
||||||
auto aut = post.run(nba, 0);
|
auto aut = post.run(nba, 0);
|
||||||
const double conversion_time = sw.stop();
|
const double conversion_time = sw.stop();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -620,14 +620,14 @@ namespace
|
||||||
st->in_states= s.states;
|
st->in_states= s.states;
|
||||||
st->in_edges = s.transitions;
|
st->in_edges = s.transitions;
|
||||||
st->in_transitions = s.sub_transitions;
|
st->in_transitions = s.sub_transitions;
|
||||||
st->in_acc = aut->accpair_count;
|
st->in_acc = aut->aut->num_sets() / 2;
|
||||||
|
|
||||||
st->in_scc = spot::scc_info(aut->aut).scc_count();
|
st->in_scc = spot::scc_info(aut->aut).scc_count();
|
||||||
}
|
}
|
||||||
// convert it into TGBA for further processing
|
// convert it into TGBA for further processing
|
||||||
if (verbose)
|
if (verbose)
|
||||||
std::cerr << "info: converting " << type << " to TGBA\n";
|
std::cerr << "info: converting " << type << " to TGBA\n";
|
||||||
res = dstar_to_tgba(aut);
|
res = remove_fin(aut->aut);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
#include "misc/timer.hh"
|
#include "misc/timer.hh"
|
||||||
#include "twaalgos/lbtt.hh"
|
#include "twaalgos/lbtt.hh"
|
||||||
#include "twaalgos/relabel.hh"
|
#include "twaalgos/relabel.hh"
|
||||||
|
#include "twaalgos/totgba.hh"
|
||||||
#include "parseaut/public.hh"
|
#include "parseaut/public.hh"
|
||||||
#include "dstarparse/public.hh"
|
#include "dstarparse/public.hh"
|
||||||
|
|
||||||
|
|
@ -185,7 +186,7 @@ namespace
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res = dstar_to_tgba(aut);
|
res = aut->aut;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
## -*- coding: utf-8 -*-
|
## -*- coding: utf-8 -*-
|
||||||
## Copyright (C) 2013 Laboratoire de Recherche et Développement de
|
## Copyright (C) 2013, 2015 Laboratoire de Recherche et Développement
|
||||||
## l'Epita (LRDE).
|
## de l'Epita (LRDE).
|
||||||
##
|
##
|
||||||
## This file is part of Spot, a model checking library.
|
## This file is part of Spot, a model checking library.
|
||||||
##
|
##
|
||||||
|
|
@ -52,10 +52,6 @@ EXTRA_DIST = $(DSTARPARSE_YY)
|
||||||
|
|
||||||
libdstarparse_la_SOURCES = \
|
libdstarparse_la_SOURCES = \
|
||||||
fmterror.cc \
|
fmterror.cc \
|
||||||
dra2ba.cc \
|
|
||||||
dstar2tgba.cc \
|
|
||||||
nra2nba.cc \
|
|
||||||
nsa2tgba.cc \
|
|
||||||
$(FROM_DSTARPARSE_YY) \
|
$(FROM_DSTARPARSE_YY) \
|
||||||
dstarscan.ll \
|
dstarscan.ll \
|
||||||
parsedecl.hh
|
parsedecl.hh
|
||||||
|
|
|
||||||
|
|
@ -1,352 +0,0 @@
|
||||||
// -*- coding: utf-8 -*-
|
|
||||||
// Copyright (C) 2013, 2014, 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/>.
|
|
||||||
|
|
||||||
#include "public.hh"
|
|
||||||
#include "twa/twamask.hh"
|
|
||||||
#include "twaalgos/scc.hh"
|
|
||||||
#include "twaalgos/reachiter.hh"
|
|
||||||
#include "twaalgos/gtec/gtec.hh"
|
|
||||||
#include "twaalgos/sccfilter.hh"
|
|
||||||
#include "twaalgos/dot.hh"
|
|
||||||
|
|
||||||
namespace spot
|
|
||||||
{
|
|
||||||
|
|
||||||
// IMPORTANT NOTE: If you attempt to follow Krishnan et
|
|
||||||
// al. (ISAAC'94) paper while reading this code, make sure you
|
|
||||||
// understand the difference between their Rabin acceptance
|
|
||||||
// definition and the one we are using.
|
|
||||||
//
|
|
||||||
// Here, a cycle is accepting in a Rabin automaton if there exists
|
|
||||||
// an acceptance pair (Lᵢ, Uᵢ) such that some states from Lᵢ are
|
|
||||||
// visited while no states from Uᵢ are visited. This is the
|
|
||||||
// same definition used by ltl2dstar.
|
|
||||||
//
|
|
||||||
// In the Krishnan et al. paper, a cycle is accepting in a Rabin
|
|
||||||
// automaton if there exists an acceptance pair (Lᵢ, Uᵢ) such that
|
|
||||||
// some states from Lᵢ are visited and all visited states belongs to
|
|
||||||
// Uᵢ. In other words, you can switch from one definition to
|
|
||||||
// the other by complementing the Uᵢ set.
|
|
||||||
//
|
|
||||||
// This is a source of confusion; you have been warned.
|
|
||||||
|
|
||||||
|
|
||||||
// This function is defined in nra2nba.cc, and used only here.
|
|
||||||
SPOT_LOCAL
|
|
||||||
twa_graph_ptr nra_to_nba(const const_dstar_aut_ptr& nra,
|
|
||||||
const const_twa_ptr& aut);
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
typedef std::list<const state*> state_list;
|
|
||||||
|
|
||||||
// The functions that take aut and dra as first arguments are
|
|
||||||
// either called on the main automaton, in which case dra->aut ==
|
|
||||||
// aut, or it is called on a sub-automaton in which case aut is a
|
|
||||||
// masked version of dra->aut. So we should always explore the
|
|
||||||
// automaton aut, but because the state of aut are states of
|
|
||||||
// dra->aut, we can use dra->aut to get labels, and dra->acccs to
|
|
||||||
// retrive acceptances.
|
|
||||||
|
|
||||||
static bool
|
|
||||||
filter_states(const const_twa_ptr& aut,
|
|
||||||
const const_dstar_aut_ptr& dra,
|
|
||||||
const state_list& sl,
|
|
||||||
state_list& final,
|
|
||||||
state_list& nonfinal);
|
|
||||||
|
|
||||||
static bool
|
|
||||||
filter_scc(const const_twa_ptr& aut,
|
|
||||||
const const_dstar_aut_ptr& dra,
|
|
||||||
state_list& final,
|
|
||||||
state_list& nonfinal)
|
|
||||||
{
|
|
||||||
// Iterate over all non-trivial SCCs.
|
|
||||||
scc_map sm(aut);
|
|
||||||
sm.build_map();
|
|
||||||
for (unsigned scc_max = sm.scc_count(), scc = 0;
|
|
||||||
scc < scc_max; ++scc)
|
|
||||||
{
|
|
||||||
if (sm.trivial(scc))
|
|
||||||
{
|
|
||||||
nonfinal.push_back(sm.one_state_of(scc));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the list of states of that SCC
|
|
||||||
const std::list<const state*>& sl = sm.states_of(scc);
|
|
||||||
assert(!sl.empty());
|
|
||||||
if (!filter_states(aut, dra, sl, final, nonfinal))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
filter_states(const const_twa_ptr& aut,
|
|
||||||
const const_dstar_aut_ptr& dra,
|
|
||||||
const state_list& sl,
|
|
||||||
state_list& final,
|
|
||||||
state_list& nonfinal)
|
|
||||||
{
|
|
||||||
// Check whether the SCC composed of all states in sl contains
|
|
||||||
// non-accepting cycles.
|
|
||||||
//
|
|
||||||
// A cycle is accepting (in a Rabin automaton) if there exists
|
|
||||||
// an acceptance pair (Lᵢ, Uᵢ) such that some states from Lᵢ
|
|
||||||
// are visited while no states from Uᵢ are visited.
|
|
||||||
//
|
|
||||||
// Consequently, a cycle is non-accepting if for all acceptance
|
|
||||||
// pairs (Lᵢ, Uᵢ), either no states from Lᵢ are visited or some
|
|
||||||
// states from Uᵢ are visited. (This corresponds to an
|
|
||||||
// accepting cycle with Streett acceptance.)
|
|
||||||
//
|
|
||||||
// Now we consider the SCC as one large cycle and check its
|
|
||||||
// intersection with all Lᵢs and Uᵢs. Let l=[l₁,l₂,...] and
|
|
||||||
// u=[u₁,u₂,...] be bitvectors where bit lᵢ (resp. uᵢ)
|
|
||||||
// indicates that Lᵢ (resp. Uᵢ) has been visited in the SCC.
|
|
||||||
state_list::const_iterator it = sl.begin();
|
|
||||||
int num = dra->aut->state_number(*it++);
|
|
||||||
bitvect* l = dra->accsets->at(num * 2).clone();
|
|
||||||
bitvect* u = dra->accsets->at(num * 2 + 1).clone();
|
|
||||||
for (; it != sl.end(); ++it)
|
|
||||||
{
|
|
||||||
num = dra->aut->state_number(*it);
|
|
||||||
*l |= dra->accsets->at(num * 2);
|
|
||||||
*u |= dra->accsets->at(num * 2 + 1);
|
|
||||||
}
|
|
||||||
// If we have l&!u = [0,0,...] that means that the cycle formed
|
|
||||||
// by the entire SCC is not accepting. However that does not
|
|
||||||
// necessarily imply that all cycles in the SCC are also
|
|
||||||
// non-accepting. We may have a smaller cycle that is
|
|
||||||
// accepting, but which becomes non-accepting when extended with
|
|
||||||
// more states.
|
|
||||||
*l -= *u;
|
|
||||||
delete u;
|
|
||||||
if (l->is_fully_clear())
|
|
||||||
{
|
|
||||||
delete l;
|
|
||||||
// Check whether the SCC is accepting. We do that by simply
|
|
||||||
// converting that SCC into a TGBA and running our emptiness
|
|
||||||
// check. This is not a really smart implementation and
|
|
||||||
// could be improved.
|
|
||||||
{
|
|
||||||
state_set keep(sl.begin(), sl.end());
|
|
||||||
auto masked = build_twa_mask_keep(dra->aut, keep, sl.front());
|
|
||||||
if (!nra_to_nba(dra, masked)->is_empty())
|
|
||||||
// This SCC is not DBA-realizable.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (state_list::const_iterator i = sl.begin();
|
|
||||||
i != sl.end(); ++i)
|
|
||||||
nonfinal.push_back(*i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// The bits sets in *l corresponds to Lᵢs that have been seen
|
|
||||||
// without seeing the matching Uᵢ. In this SCC, any state in Lᵢ
|
|
||||||
// is therefore final. Otherwise we do not know: it is possible
|
|
||||||
// that there is a non-accepting cycle in the SCC that do not
|
|
||||||
// visit Lᵢ.
|
|
||||||
state_set unknown;
|
|
||||||
for (it = sl.begin(); it != sl.end(); ++it)
|
|
||||||
{
|
|
||||||
num = dra->aut->state_number(*it);
|
|
||||||
bitvect* l2 = dra->accsets->at(num * 2).clone();
|
|
||||||
*l2 &= *l;
|
|
||||||
if (!l2->is_fully_clear())
|
|
||||||
{
|
|
||||||
final.push_back(*it);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unknown.insert(*it);
|
|
||||||
}
|
|
||||||
delete l2;
|
|
||||||
}
|
|
||||||
delete l;
|
|
||||||
// Check whether it is possible to build non-accepting cycles
|
|
||||||
// using only the "unknown" states.
|
|
||||||
while (!unknown.empty())
|
|
||||||
{
|
|
||||||
//std::cerr << "unknown\n";
|
|
||||||
// Build a sub-automaton for just the unknown states,
|
|
||||||
// starting from any state in the SCC.
|
|
||||||
auto scc_mask = build_twa_mask_keep(aut, unknown, *unknown.begin());
|
|
||||||
state_list local_final;
|
|
||||||
state_list local_nonfinal;
|
|
||||||
bool dbarealizable =
|
|
||||||
filter_scc(scc_mask, dra, local_final, local_nonfinal);
|
|
||||||
if (!dbarealizable)
|
|
||||||
return false;
|
|
||||||
for (state_list::const_iterator i = local_final.begin();
|
|
||||||
i != local_final.end(); ++i)
|
|
||||||
unknown.erase(*i);
|
|
||||||
final.splice(final.end(), local_final);
|
|
||||||
for (state_list::const_iterator i = local_nonfinal.begin();
|
|
||||||
i != local_nonfinal.end(); ++i)
|
|
||||||
unknown.erase(*i);
|
|
||||||
nonfinal.splice(nonfinal.end(), local_nonfinal);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class dra_to_ba_worker: public tgba_reachable_iterator_depth_first
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
dra_to_ba_worker(const const_dstar_aut_ptr& a,
|
|
||||||
const state_set& final,
|
|
||||||
const scc_map& sm,
|
|
||||||
const std::vector<bool>& realizable):
|
|
||||||
tgba_reachable_iterator_depth_first(a->aut),
|
|
||||||
in_(a),
|
|
||||||
out_(make_twa_graph(a->aut->get_dict())),
|
|
||||||
final_(final),
|
|
||||||
num_states_(a->aut->num_states()),
|
|
||||||
sm_(sm),
|
|
||||||
realizable_(realizable)
|
|
||||||
{
|
|
||||||
out_->copy_ap_of(a->aut);
|
|
||||||
out_->prop_state_based_acc();
|
|
||||||
acc_ = out_->set_buchi();
|
|
||||||
out_->new_states(num_states_ * (a->accpair_count + 1));
|
|
||||||
out_->set_init_state(a->aut->get_init_state_number());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
twa_graph_ptr
|
|
||||||
result()
|
|
||||||
{
|
|
||||||
return out_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
process_link(const state* sin, int,
|
|
||||||
const state* sout, int,
|
|
||||||
const twa_succ_iterator* si)
|
|
||||||
{
|
|
||||||
int in = in_->aut->state_number(sin);
|
|
||||||
int out = in_->aut->state_number(sout);
|
|
||||||
unsigned in_scc = sm_.scc_of_state(sin);
|
|
||||||
|
|
||||||
bdd cond = si->current_condition();
|
|
||||||
unsigned t = out_->new_edge(in, out, cond);
|
|
||||||
|
|
||||||
if (realizable_[in_scc])
|
|
||||||
{
|
|
||||||
if (final_.find(sin) != final_.end())
|
|
||||||
out_->edge_data(t).acc = acc_;
|
|
||||||
}
|
|
||||||
else if (sm_.scc_of_state(sout) == in_scc)
|
|
||||||
{
|
|
||||||
// Create one clone of the SCC per accepting pair,
|
|
||||||
// removing states from the Ui part of the (Li, Ui) pairs.
|
|
||||||
// (Or the Ei part of Löding's (Ei, Fi) pairs.)
|
|
||||||
bitvect& l = in_->accsets->at(2 * in);
|
|
||||||
bitvect& u = in_->accsets->at(2 * in + 1);
|
|
||||||
for (size_t i = 0; i < in_->accpair_count; ++i)
|
|
||||||
{
|
|
||||||
int shift = num_states_ * (i + 1);
|
|
||||||
// In the Ui set. (Löding's Ei set.)
|
|
||||||
if (!u.get(i))
|
|
||||||
{
|
|
||||||
// Transition t1 is a non-deterministic jump
|
|
||||||
// from the original automaton to the i-th clone.
|
|
||||||
//
|
|
||||||
// Transition t2 constructs the clone.
|
|
||||||
//
|
|
||||||
// Löding creates transition t1 regardless of the
|
|
||||||
// acceptance set. We restrict it to the non-Li
|
|
||||||
// states. Both his definition and this
|
|
||||||
// implementation create more transitions than needed:
|
|
||||||
// we do not need more than one transition per
|
|
||||||
// accepting cycle.
|
|
||||||
out_->new_edge(in, out + shift, cond);
|
|
||||||
|
|
||||||
// Acceptance transitions are those in the Li
|
|
||||||
// set. (Löding's Fi set.)
|
|
||||||
out_->new_acc_edge(in + shift, out + shift, cond, l.get(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const const_dstar_aut_ptr& in_;
|
|
||||||
twa_graph_ptr out_;
|
|
||||||
const state_set& final_;
|
|
||||||
size_t num_states_;
|
|
||||||
acc_cond::mark_t acc_;
|
|
||||||
const scc_map& sm_;
|
|
||||||
const std::vector<bool>& realizable_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
twa_graph_ptr dra_to_ba(const const_dstar_aut_ptr& dra, bool* dba)
|
|
||||||
{
|
|
||||||
assert(dra->type == Rabin);
|
|
||||||
|
|
||||||
state_list final;
|
|
||||||
state_list nonfinal;
|
|
||||||
|
|
||||||
// Iterate over all non-trivial SCCs.
|
|
||||||
scc_map sm(dra->aut);
|
|
||||||
sm.build_map();
|
|
||||||
unsigned scc_max = sm.scc_count();
|
|
||||||
|
|
||||||
bool dba_realizable = true;
|
|
||||||
std::vector<bool> realizable(scc_max);
|
|
||||||
|
|
||||||
for (unsigned scc = 0; scc < scc_max; ++scc)
|
|
||||||
{
|
|
||||||
if (sm.trivial(scc))
|
|
||||||
{
|
|
||||||
realizable[scc] = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the list of states of that SCC
|
|
||||||
const std::list<const state*>& sl = sm.states_of(scc);
|
|
||||||
assert(!sl.empty());
|
|
||||||
bool scc_realizable = filter_states(dra->aut, dra, sl, final, nonfinal);
|
|
||||||
dba_realizable &= scc_realizable;
|
|
||||||
realizable[scc] = scc_realizable;
|
|
||||||
//std::cerr << "realizable[" << scc << "] = " << scc_realizable << '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dba)
|
|
||||||
*dba = dba_realizable;
|
|
||||||
|
|
||||||
// for (state_list::const_iterator i = final.begin();
|
|
||||||
// i != final.end(); ++i)
|
|
||||||
// std::cerr << dra->aut->get_label(*i) << " is final\n";
|
|
||||||
// for (state_list::const_iterator i = nonfinal.begin();
|
|
||||||
// i != nonfinal.end(); ++i)
|
|
||||||
// std::cerr << dra->aut->get_label(*i) << " is non-final\n";
|
|
||||||
|
|
||||||
state_set fs(final.begin(), final.end());
|
|
||||||
dra_to_ba_worker w(dra, fs, sm, realizable);
|
|
||||||
w.run();
|
|
||||||
return scc_filter_states(w.result());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
// -*- coding: utf-8 -*-
|
|
||||||
// Copyright (C) 2013, 2014 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/>.
|
|
||||||
|
|
||||||
#include "public.hh"
|
|
||||||
|
|
||||||
namespace spot
|
|
||||||
{
|
|
||||||
twa_graph_ptr
|
|
||||||
dstar_to_tgba(const const_dstar_aut_ptr& daut)
|
|
||||||
{
|
|
||||||
switch (daut->type)
|
|
||||||
{
|
|
||||||
case spot::Rabin:
|
|
||||||
return dra_to_ba(daut);
|
|
||||||
case spot::Streett:
|
|
||||||
return nsa_to_tgba(daut);
|
|
||||||
}
|
|
||||||
SPOT_UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -46,9 +46,12 @@
|
||||||
std::vector<bdd>::const_iterator cur_guard;
|
std::vector<bdd>::const_iterator cur_guard;
|
||||||
map_t dest_map;
|
map_t dest_map;
|
||||||
int cur_state;
|
int cur_state;
|
||||||
|
int plus;
|
||||||
|
int minus;
|
||||||
|
|
||||||
unsigned state_count = 0;
|
unsigned state_count = 0U;
|
||||||
unsigned start_state = 0;
|
unsigned start_state = 0U;
|
||||||
|
unsigned accpair_count = 0U;
|
||||||
std::vector<std::string> aps;
|
std::vector<std::string> aps;
|
||||||
|
|
||||||
bool state_count_seen:1;
|
bool state_count_seen:1;
|
||||||
|
|
@ -73,6 +76,7 @@
|
||||||
{
|
{
|
||||||
std::string* str;
|
std::string* str;
|
||||||
unsigned int num;
|
unsigned int num;
|
||||||
|
spot::acc_cond::mark_t acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
%code
|
%code
|
||||||
|
|
@ -102,6 +106,7 @@
|
||||||
%token <num> NUMBER "number";
|
%token <num> NUMBER "number";
|
||||||
|
|
||||||
%type <num> sign
|
%type <num> sign
|
||||||
|
%type <acc> accsigs state_accsig
|
||||||
|
|
||||||
%destructor { delete $$; } <str>
|
%destructor { delete $$; } <str>
|
||||||
%printer {
|
%printer {
|
||||||
|
|
@ -117,9 +122,18 @@ dstar: header ENDOFHEADER eols states
|
||||||
eols : EOL | eols EOL
|
eols : EOL | eols EOL
|
||||||
opt_eols: | opt_eols EOL
|
opt_eols: | opt_eols EOL
|
||||||
|
|
||||||
auttype: DRA { result.d->type = spot::Rabin; }
|
auttype: DRA
|
||||||
| DSA { result.d->type = spot::Streett; }
|
{
|
||||||
|
result.d->type = spot::Rabin;
|
||||||
|
result.plus = 1;
|
||||||
|
result.minus = 0;
|
||||||
|
}
|
||||||
|
| DSA
|
||||||
|
{
|
||||||
|
result.d->type = spot::Streett;
|
||||||
|
result.plus = 0;
|
||||||
|
result.minus = 1;
|
||||||
|
}
|
||||||
|
|
||||||
header: auttype opt_eols V2 opt_eols EXPLICIT opt_eols sizes
|
header: auttype opt_eols V2 opt_eols EXPLICIT opt_eols sizes
|
||||||
{
|
{
|
||||||
|
|
@ -168,8 +182,12 @@ sizes:
|
||||||
}
|
}
|
||||||
| sizes ACCPAIRS opt_eols NUMBER opt_eols
|
| sizes ACCPAIRS opt_eols NUMBER opt_eols
|
||||||
{
|
{
|
||||||
result.d->accpair_count = $4;
|
result.accpair_count = $4;
|
||||||
result.accpair_count_seen = true;
|
result.accpair_count_seen = true;
|
||||||
|
result.d->aut->set_acceptance(2 * $4,
|
||||||
|
result.d->type == spot::Rabin ?
|
||||||
|
spot::acc_cond::acc_code::rabin($4) :
|
||||||
|
spot::acc_cond::acc_code::streett($4));
|
||||||
}
|
}
|
||||||
| sizes STATES opt_eols NUMBER opt_eols
|
| sizes STATES opt_eols NUMBER opt_eols
|
||||||
{
|
{
|
||||||
|
|
@ -228,27 +246,30 @@ state_id: STATE opt_eols NUMBER opt_eols opt_name
|
||||||
result.cur_state = $3;
|
result.cur_state = $3;
|
||||||
}
|
}
|
||||||
|
|
||||||
sign: '+' { $$ = 0; }
|
sign: '+' { $$ = result.plus; }
|
||||||
| '-' { $$ = 1; }
|
| '-' { $$ = result.minus; }
|
||||||
|
|
||||||
// Membership to a pair is represented as (+NUM,-NUM)
|
// Membership to a pair is represented as (+NUM,-NUM)
|
||||||
accsigs: opt_eols
|
accsigs: opt_eols
|
||||||
|
{
|
||||||
|
$$ = 0U;
|
||||||
|
}
|
||||||
| accsigs sign NUMBER opt_eols
|
| accsigs sign NUMBER opt_eols
|
||||||
{
|
{
|
||||||
if ((unsigned) result.cur_state >= result.state_count)
|
if ((unsigned) result.cur_state >= result.state_count)
|
||||||
break;
|
break;
|
||||||
assert(result.d->accsets);
|
if ($3 < result.accpair_count)
|
||||||
if ($3 < result.d->accpair_count)
|
|
||||||
{
|
{
|
||||||
result.d->accsets->at(result.cur_state * 2 + $2).set($3);
|
$$ = $1;
|
||||||
|
$$.set($3 * 2 + $2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::ostringstream o;
|
std::ostringstream o;
|
||||||
if (result.d->accpair_count > 0)
|
if (result.accpair_count > 0)
|
||||||
{
|
{
|
||||||
o << "acceptance pairs should be in the range [0.."
|
o << "acceptance pairs should be in the range [0.."
|
||||||
<< result.d->accpair_count - 1<< "]";
|
<< result.accpair_count - 1 << "]";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -258,7 +279,7 @@ accsigs: opt_eols
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state_accsig: ACCSIG accsigs
|
state_accsig: ACCSIG accsigs { $$ = $2; }
|
||||||
|
|
||||||
transitions:
|
transitions:
|
||||||
| transitions NUMBER opt_eols
|
| transitions NUMBER opt_eols
|
||||||
|
|
@ -273,9 +294,8 @@ transitions:
|
||||||
states:
|
states:
|
||||||
| states state_id state_accsig transitions
|
| states state_id state_accsig transitions
|
||||||
{
|
{
|
||||||
for (map_t::const_iterator i = result.dest_map.begin();
|
for (auto i: result.dest_map)
|
||||||
i != result.dest_map.end(); ++i)
|
result.d->aut->new_edge(result.cur_state, i.first, i.second, $3);
|
||||||
result.d->aut->new_edge(result.cur_state, i->first, i->second);
|
|
||||||
}
|
}
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
@ -301,9 +321,6 @@ static void fill_guards(result_& r)
|
||||||
|
|
||||||
delete[] vars;
|
delete[] vars;
|
||||||
r.cur_guard = r.guards.end();
|
r.cur_guard = r.guards.end();
|
||||||
|
|
||||||
r.d->accsets = spot::make_bitvect_array(r.d->accpair_count,
|
|
||||||
2 * r.state_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -331,14 +348,15 @@ namespace spot
|
||||||
result_ r;
|
result_ r;
|
||||||
r.d = std::make_shared<spot::dstar_aut>();
|
r.d = std::make_shared<spot::dstar_aut>();
|
||||||
r.d->aut = make_twa_graph(dict);
|
r.d->aut = make_twa_graph(dict);
|
||||||
r.d->accsets = 0;
|
r.d->aut->prop_deterministic(true);
|
||||||
|
r.d->aut->prop_state_based_acc(true);
|
||||||
r.env = &env;
|
r.env = &env;
|
||||||
dstaryy::parser parser(error_list, r);
|
dstaryy::parser parser(error_list, r);
|
||||||
parser.set_debug_level(debug);
|
parser.set_debug_level(debug);
|
||||||
parser.parse();
|
parser.parse();
|
||||||
dstaryyclose();
|
dstaryyclose();
|
||||||
|
|
||||||
if (!r.d->aut || !r.d->accsets)
|
if (!r.d->aut)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return r.d;
|
return r.d;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,131 +0,0 @@
|
||||||
// -*- coding: utf-8 -*-
|
|
||||||
// Copyright (C) 2013, 2014, 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/>.
|
|
||||||
|
|
||||||
#include "public.hh"
|
|
||||||
#include "twaalgos/reachiter.hh"
|
|
||||||
#include "twaalgos/sccfilter.hh"
|
|
||||||
|
|
||||||
namespace spot
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
// Christof Löding's Diploma Thesis: Methods for the
|
|
||||||
// Transformation of ω-Automata: Complexity and Connection to
|
|
||||||
// Second Order Logic. Section 3.4.3: Rabin to Büchi.
|
|
||||||
//
|
|
||||||
// However beware that the {...,(Ei,Fi),...} pairs used by Löding
|
|
||||||
// are reversed compared to the {...,(Li,Ui),...} pairs used by
|
|
||||||
// several other people. We have Ei=Ui and Fi=Li.
|
|
||||||
class nra_to_nba_worker: public tgba_reachable_iterator_depth_first
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// AUT is the automaton we iterate on, while A is the automaton
|
|
||||||
// we read the acceptance conditions from. Separating the two
|
|
||||||
// makes its possible to mask AUT, as needed in dra_to_ba().
|
|
||||||
nra_to_nba_worker(const const_dstar_aut_ptr& a, const_twa_ptr aut):
|
|
||||||
tgba_reachable_iterator_depth_first(aut),
|
|
||||||
out_(make_twa_graph(aut->get_dict())),
|
|
||||||
d_(a),
|
|
||||||
num_states_(a->aut->num_states())
|
|
||||||
{
|
|
||||||
out_->copy_ap_of(aut);
|
|
||||||
out_->set_buchi();
|
|
||||||
out_->prop_state_based_acc();
|
|
||||||
out_->new_states(num_states_ * (d_->accpair_count + 1));
|
|
||||||
// This converts the initial state of aut (not a->aut) into a
|
|
||||||
// state number in a->aut.
|
|
||||||
auto i = aut->get_init_state();
|
|
||||||
out_->set_init_state(a->aut->state_number(i));
|
|
||||||
i->destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
twa_graph_ptr
|
|
||||||
result()
|
|
||||||
{
|
|
||||||
return out_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
process_link(const state* sin, int,
|
|
||||||
const state* sout, int,
|
|
||||||
const twa_succ_iterator* si)
|
|
||||||
{
|
|
||||||
int in = d_->aut->state_number(sin);
|
|
||||||
int out = d_->aut->state_number(sout);
|
|
||||||
|
|
||||||
bdd cond = si->current_condition();
|
|
||||||
out_->new_edge(in, out, cond);
|
|
||||||
|
|
||||||
// Create one clone of the automaton per accepting pair,
|
|
||||||
// removing states from the Ui part of the (Li, Ui) pairs.
|
|
||||||
// (Or the Ei part of Löding's (Ei, Fi) pairs.)
|
|
||||||
bitvect& l = d_->accsets->at(2 * in);
|
|
||||||
bitvect& u = d_->accsets->at(2 * in + 1);
|
|
||||||
for (size_t i = 0; i < d_->accpair_count; ++i)
|
|
||||||
{
|
|
||||||
int shift = num_states_ * (i + 1);
|
|
||||||
// In the Ui set. (Löding's Ei set.)
|
|
||||||
if (!u.get(i))
|
|
||||||
{
|
|
||||||
// Transition t1 is a non-deterministic jump
|
|
||||||
// from the original automaton to the i-th clone.
|
|
||||||
//
|
|
||||||
// Transition t2 constructs the clone.
|
|
||||||
//
|
|
||||||
// Löding creates transition t1 regardless of the
|
|
||||||
// acceptance set. We restrict it to the non-Li
|
|
||||||
// states. Both his definition and this
|
|
||||||
// implementation create more transitions than needed:
|
|
||||||
// we do not need more than one transition per
|
|
||||||
// accepting cycle.
|
|
||||||
out_->new_edge(in, out + shift, cond);
|
|
||||||
|
|
||||||
// A transition is accepting if it is in the Li
|
|
||||||
// set. (Löding's Fi set.)
|
|
||||||
out_->new_acc_edge(in + shift, out + shift, cond, l.get(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
twa_graph_ptr out_;
|
|
||||||
const_dstar_aut_ptr d_;
|
|
||||||
size_t num_states_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// In dra_to_dba() we call this function with a second argument
|
|
||||||
// that is a masked version of nra->aut.
|
|
||||||
SPOT_LOCAL
|
|
||||||
twa_graph_ptr nra_to_nba(const const_dstar_aut_ptr& nra,
|
|
||||||
const const_twa_ptr& aut)
|
|
||||||
{
|
|
||||||
assert(nra->type == Rabin);
|
|
||||||
nra_to_nba_worker w(nra, aut);
|
|
||||||
w.run();
|
|
||||||
return scc_filter_states(w.result());
|
|
||||||
}
|
|
||||||
|
|
||||||
twa_graph_ptr nra_to_nba(const const_dstar_aut_ptr& nra)
|
|
||||||
{
|
|
||||||
return nra_to_nba(nra, nra->aut);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,206 +0,0 @@
|
||||||
// -*- coding: utf-8 -*-
|
|
||||||
// Copyright (C) 2013, 2014, 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/>.
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <deque>
|
|
||||||
#include "public.hh"
|
|
||||||
#include "twaalgos/sccfilter.hh"
|
|
||||||
#include "ltlenv/defaultenv.hh"
|
|
||||||
#include "priv/accmap.hh"
|
|
||||||
|
|
||||||
namespace spot
|
|
||||||
{
|
|
||||||
// Christof Löding's Diploma Thesis: Methods for the
|
|
||||||
// Transformation of ω-Automata: Complexity and Connection to
|
|
||||||
// Second Order Logic. Section 3.4.3, gives a transition
|
|
||||||
// from Streett with |Q| states to BA with |Q|*(4^n-3^n+2)
|
|
||||||
// states, if n is the number of acceptance pairs.
|
|
||||||
//
|
|
||||||
// Duret-Lutz et al. (ATVA'2009): On-the-fly Emptiness Check of
|
|
||||||
// Transition-based Streett Automata. Section 3.3 contains a
|
|
||||||
// conversion from transition-based Streett Automata to TGBA using
|
|
||||||
// the generalized Büchi acceptance to limit the explosion. It goes
|
|
||||||
// from Streett with |Q| states to (T)GBA with |Q|*(2^n+1) states.
|
|
||||||
// However the definition of the number of acceptance sets in that
|
|
||||||
// paper is suboptimal: only n are needed, not 2^n.
|
|
||||||
//
|
|
||||||
// This implements this second version.
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
// A state in the resulting automaton corresponds is either a
|
|
||||||
// state of the original automaton (in which case bv == 0) or a
|
|
||||||
// state of the original automaton associated to a set of pending
|
|
||||||
// acceptance represented by a bitvect.
|
|
||||||
|
|
||||||
struct build_state
|
|
||||||
{
|
|
||||||
int s;
|
|
||||||
const bitvect* pend;
|
|
||||||
|
|
||||||
build_state(int st, const bitvect* bv = 0):
|
|
||||||
s(st),
|
|
||||||
pend(bv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct build_state_hash
|
|
||||||
{
|
|
||||||
size_t
|
|
||||||
operator()(const build_state& s) const
|
|
||||||
{
|
|
||||||
if (!s.pend)
|
|
||||||
return s.s;
|
|
||||||
else
|
|
||||||
return s.s ^ s.pend->hash();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct build_state_equal
|
|
||||||
{
|
|
||||||
bool
|
|
||||||
operator()(const build_state& left,
|
|
||||||
const build_state& right) const
|
|
||||||
{
|
|
||||||
if (left.s != right.s)
|
|
||||||
return false;
|
|
||||||
if (left.pend == right.pend)
|
|
||||||
return true;
|
|
||||||
if (!right.pend || !left.pend)
|
|
||||||
return false;
|
|
||||||
return *left.pend == *right.pend;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Associate the build state to its number.
|
|
||||||
typedef std::unordered_map<build_state, int,
|
|
||||||
build_state_hash, build_state_equal> bs2num_map;
|
|
||||||
|
|
||||||
// Queue of state to be processed.
|
|
||||||
typedef std::deque<build_state> queue_t;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
twa_graph_ptr nsa_to_tgba(const const_dstar_aut_ptr& nsa)
|
|
||||||
{
|
|
||||||
assert(nsa->type == Streett);
|
|
||||||
auto a = nsa->aut;
|
|
||||||
auto res = make_twa_graph(a->get_dict());
|
|
||||||
res->copy_ap_of(a);
|
|
||||||
|
|
||||||
// Create accpair_count acceptance sets for the output.
|
|
||||||
unsigned npairs = nsa->accpair_count;
|
|
||||||
acc_mapper_consecutive_int acc_b(res, npairs);
|
|
||||||
|
|
||||||
// These maps make it possible to convert build_state to number
|
|
||||||
// and vice-versa.
|
|
||||||
bs2num_map bs2num;
|
|
||||||
|
|
||||||
queue_t todo;
|
|
||||||
|
|
||||||
build_state s(a->get_init_state_number());
|
|
||||||
bs2num[s] = res->new_state();
|
|
||||||
todo.push_back(s);
|
|
||||||
|
|
||||||
while (!todo.empty())
|
|
||||||
{
|
|
||||||
s = todo.front();
|
|
||||||
todo.pop_front();
|
|
||||||
int src = bs2num[s];
|
|
||||||
|
|
||||||
for (auto& t: a->out(s.s))
|
|
||||||
{
|
|
||||||
bitvect* pend = 0;
|
|
||||||
acc_cond::mark_t acc = 0U;
|
|
||||||
if (s.pend)
|
|
||||||
{
|
|
||||||
pend = s.pend->clone();
|
|
||||||
*pend |= nsa->accsets->at(2 * t.dst); // L
|
|
||||||
*pend -= nsa->accsets->at(2 * t.dst + 1); // U
|
|
||||||
|
|
||||||
for (size_t i = 0; i < npairs; ++i)
|
|
||||||
if (!pend->get(i))
|
|
||||||
acc |= acc_b.lookup(i).second;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
build_state d(t.dst, pend);
|
|
||||||
// Have we already seen this destination?
|
|
||||||
int dest;
|
|
||||||
auto dres = bs2num.emplace(d, 0);
|
|
||||||
if (!dres.second)
|
|
||||||
{
|
|
||||||
dest = dres.first->second;
|
|
||||||
delete d.pend;
|
|
||||||
}
|
|
||||||
else // No, this is a new state
|
|
||||||
{
|
|
||||||
dest = dres.first->second = res->new_state();
|
|
||||||
todo.push_back(d);
|
|
||||||
}
|
|
||||||
res->new_edge(src, dest, t.cond, acc);
|
|
||||||
|
|
||||||
// Jump to level ∅
|
|
||||||
if (s.pend == 0)
|
|
||||||
{
|
|
||||||
bitvect* pend = make_bitvect(npairs);
|
|
||||||
build_state d(t.dst, pend);
|
|
||||||
// Have we already seen this destination?
|
|
||||||
int dest;
|
|
||||||
auto dres = bs2num.emplace(d, 0);
|
|
||||||
if (!dres.second)
|
|
||||||
{
|
|
||||||
dest = dres.first->second;
|
|
||||||
delete d.pend;
|
|
||||||
}
|
|
||||||
else // No, this is a new state
|
|
||||||
{
|
|
||||||
dest = dres.first->second = res->new_state();
|
|
||||||
todo.push_back(d);
|
|
||||||
}
|
|
||||||
res->new_edge(src, dest, t.cond);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// {
|
|
||||||
// bs2num_map::iterator i = bs2num.begin();
|
|
||||||
// while (i != bs2num.end())
|
|
||||||
// {
|
|
||||||
// std::cerr << i->second << ": (" << i->first.s << ',';
|
|
||||||
// if (i->first.pend)
|
|
||||||
// std::cerr << *i->first.pend << ")\n";
|
|
||||||
// else
|
|
||||||
// std::cerr << "-)\n";
|
|
||||||
// ++i;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Cleanup the bs2num map.
|
|
||||||
bs2num_map::iterator i = bs2num.begin();
|
|
||||||
while (i != bs2num.end())
|
|
||||||
delete (i++)->first.pend;
|
|
||||||
|
|
||||||
res->acc().set_generalized_buchi();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// -*- coding: utf-8 -*-
|
// -*- coding: utf-8 -*-
|
||||||
// Copyright (C) 2013, 2014 Laboratoire de Recherche et Développement
|
// Copyright (C) 2013, 2014, 2015 Laboratoire de Recherche et Développement
|
||||||
// de l'Epita (LRDE).
|
// de l'Epita (LRDE).
|
||||||
//
|
//
|
||||||
// This file is part of Spot, a model checking library.
|
// This file is part of Spot, a model checking library.
|
||||||
|
|
@ -26,7 +26,6 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <misc/bitvect.hh>
|
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
@ -49,20 +48,6 @@ namespace spot
|
||||||
twa_graph_ptr aut;
|
twa_graph_ptr aut;
|
||||||
/// Type of the acceptance.
|
/// Type of the acceptance.
|
||||||
dstar_type type;
|
dstar_type type;
|
||||||
/// Number of acceptance pairs.
|
|
||||||
size_t accpair_count;
|
|
||||||
/// \brief acceptance sets encoded as 2*num_state bit-vectors of
|
|
||||||
/// num_pairs bits
|
|
||||||
///
|
|
||||||
/// Assuming F={(L₀,U₀),…,(Lᵢ,Uᵢ),…},
|
|
||||||
/// s∈Lᵢ iff <code>accsets->at(s * 2).get(i)</code>,
|
|
||||||
/// s∈Uᵢ iff <code>accsets->at(s * 2 + 1).get(i)</code>.
|
|
||||||
bitvect_array* accsets;
|
|
||||||
|
|
||||||
~dstar_aut()
|
|
||||||
{
|
|
||||||
delete accsets;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<dstar_aut> dstar_aut_ptr;
|
typedef std::shared_ptr<dstar_aut> dstar_aut_ptr;
|
||||||
|
|
@ -102,49 +87,5 @@ namespace spot
|
||||||
format_dstar_parse_errors(std::ostream& os,
|
format_dstar_parse_errors(std::ostream& os,
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
dstar_parse_error_list& error_list);
|
dstar_parse_error_list& error_list);
|
||||||
|
|
||||||
|
|
||||||
/// \brief Convert a non-deterministic Rabin automaton into a
|
|
||||||
/// non-deterministic Büchi automaton.
|
|
||||||
SPOT_API twa_graph_ptr
|
|
||||||
nra_to_nba(const const_dstar_aut_ptr& nra);
|
|
||||||
|
|
||||||
/// \brief Convert a non-deterministic Rabin automaton into a
|
|
||||||
/// non-deterministic Büchi automaton.
|
|
||||||
///
|
|
||||||
/// This version simply ignores all states in \a ignore.
|
|
||||||
SPOT_API twa_graph_ptr
|
|
||||||
nra_to_nba(const const_dstar_aut_ptr& nra, const state_set* ignore);
|
|
||||||
|
|
||||||
/// \brief Convert a deterministic Rabin automaton into a
|
|
||||||
/// Büchi automaton, deterministic when possible.
|
|
||||||
///
|
|
||||||
/// See "Deterministic ω-automata vis-a-vis Deterministic Büchi
|
|
||||||
/// Automata", S. Krishnan, A. Puri, and R. Brayton (ISAAC'94) for
|
|
||||||
/// more details about a DRA->DBA construction.
|
|
||||||
///
|
|
||||||
/// We essentially apply this method SCC-wise. If an SCC is
|
|
||||||
/// DBA-realizable, we duplicate it in the output, fixing just
|
|
||||||
/// the acceptance states. If an SCC is not DBA-realizable,
|
|
||||||
/// then we apply the more usual conversion from Rabin to NBA
|
|
||||||
/// for this part.
|
|
||||||
///
|
|
||||||
/// If the optional \a dba_output argument is non-null, the
|
|
||||||
/// pointed Boolean will be updated to indicate whether the
|
|
||||||
/// returned Büchi automaton is deterministic.
|
|
||||||
SPOT_API twa_graph_ptr
|
|
||||||
dra_to_ba(const const_dstar_aut_ptr& dra, bool* dba_output = 0);
|
|
||||||
|
|
||||||
/// \brief Convert a non-deterministic Streett automaton into a
|
|
||||||
/// non-deterministic tgba.
|
|
||||||
SPOT_API twa_graph_ptr
|
|
||||||
nsa_to_tgba(const const_dstar_aut_ptr& nra);
|
|
||||||
|
|
||||||
/// \brief Convert a Rabin or Streett automaton into a TGBA.
|
|
||||||
///
|
|
||||||
/// This function calls dra_to_ba() or nsa_to_tgba().
|
|
||||||
SPOT_API twa_graph_ptr
|
|
||||||
dstar_to_tgba(const const_dstar_aut_ptr& dstar);
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ test 3 = "`../../bin/ltl2tgba -B 'G(a|G(b|Fc))' --stats=%s`"
|
||||||
# This 7-state DRA (built with
|
# This 7-state DRA (built with
|
||||||
# ltlfilt -f 'F(a & GFb) | (Fc & Fa & F(c & GF!b))' -l |
|
# ltlfilt -f 'F(a & GFb) | (Fc & Fa & F(c & GF!b))' -l |
|
||||||
# ltl2dstar --ltl2nba=spin:ltl2tgba@-sD - -
|
# ltl2dstar --ltl2nba=spin:ltl2tgba@-sD - -
|
||||||
# should be converted in into a 6-state DBA.
|
# should be converted in into a 5-state DBA.
|
||||||
cat >in.dra <<EOF
|
cat >in.dra <<EOF
|
||||||
DRA v2 explicit
|
DRA v2 explicit
|
||||||
Comment: "Union{Safra[NBA=3],Safra[NBA=5]}"
|
Comment: "Union{Safra[NBA=3],Safra[NBA=5]}"
|
||||||
|
|
@ -221,7 +221,7 @@ Acc-Sig:
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
run 0 ../../bin/dstar2tgba in.dra -BD --stats=%s > out.stat
|
run 0 ../../bin/dstar2tgba in.dra -BD --stats=%s > out.stat
|
||||||
test 6 = "`cat out.stat`"
|
test 5 = "`cat out.stat`"
|
||||||
|
|
||||||
# Only one state should be accepting. In spot 1.2.x an initial state
|
# Only one state should be accepting. In spot 1.2.x an initial state
|
||||||
# in a trivial SCC was marked as accepting: this is superfluous.
|
# in a trivial SCC was marked as accepting: this is superfluous.
|
||||||
|
|
|
||||||
|
|
@ -68,9 +68,9 @@ digraph G {
|
||||||
0 -> 0 [label="a & !b"]
|
0 -> 0 [label="a & !b"]
|
||||||
0 -> 1 [label="!a & !b"]
|
0 -> 1 [label="!a & !b"]
|
||||||
0 -> 2 [label="b"]
|
0 -> 2 [label="b"]
|
||||||
1 [label="1"]
|
1 [label="1\n{0}"]
|
||||||
1 -> 1 [label="1"]
|
1 -> 1 [label="1"]
|
||||||
2 [label="2"]
|
2 [label="2\n{1}"]
|
||||||
2 -> 2 [label="1"]
|
2 -> 2 [label="1"]
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
@ -78,7 +78,7 @@ EOF
|
||||||
diff expected stdout
|
diff expected stdout
|
||||||
|
|
||||||
|
|
||||||
run 0 ../ikwiad -XDD dra.dstar | tee stdout
|
run 0 ../ikwiad -XDB -R3 dra.dstar | tee stdout
|
||||||
|
|
||||||
cat >expected <<EOF
|
cat >expected <<EOF
|
||||||
digraph G {
|
digraph G {
|
||||||
|
|
@ -130,39 +130,26 @@ digraph G {
|
||||||
rankdir=LR
|
rankdir=LR
|
||||||
node [shape="circle"]
|
node [shape="circle"]
|
||||||
I [label="", style=invis, width=0]
|
I [label="", style=invis, width=0]
|
||||||
I -> 0
|
I -> 1
|
||||||
0 [label="0"]
|
0 [label="0"]
|
||||||
0 -> 1 [label="1"]
|
0 -> 0 [label="!a"]
|
||||||
0 -> 2 [label="1"]
|
0 -> 2 [label="a"]
|
||||||
1 [label="1"]
|
1 [label="1"]
|
||||||
1 -> 1 [label="!a"]
|
1 -> 0 [label="1"]
|
||||||
1 -> 2 [label="!a"]
|
|
||||||
1 -> 3 [label="a"]
|
|
||||||
1 -> 4 [label="a"]
|
|
||||||
2 [label="2"]
|
2 [label="2"]
|
||||||
2 -> 5 [label="!a"]
|
2 -> 0 [label="!a"]
|
||||||
2 -> 4 [label="a\n{0}"]
|
2 -> 2 [label="a"]
|
||||||
3 [label="3"]
|
2 -> 3 [label="a"]
|
||||||
3 -> 1 [label="!a"]
|
3 [label="3", peripheries=2]
|
||||||
3 -> 2 [label="!a"]
|
|
||||||
3 -> 3 [label="a"]
|
3 -> 3 [label="a"]
|
||||||
3 -> 4 [label="a"]
|
|
||||||
4 [label="4"]
|
|
||||||
4 -> 5 [label="!a"]
|
|
||||||
4 -> 4 [label="a\n{0}"]
|
|
||||||
5 [label="5"]
|
|
||||||
5 -> 5 [label="!a"]
|
|
||||||
5 -> 6 [label="a"]
|
|
||||||
6 [label="6"]
|
|
||||||
6 -> 5 [label="!a"]
|
|
||||||
6 -> 6 [label="a"]
|
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
diff expected stdout
|
diff expected stdout
|
||||||
|
|
||||||
test "`../../bin/dstar2tgba -D dsa.dstar --stats '%s %t %p %d'`" = "2 5 0 0"
|
# These one could be reduced to 2 5 0 0 and 3 8 1 0
|
||||||
test "`../../bin/dstar2tgba -DC dsa.dstar --stats '%s %t %p %d'`" = "3 8 1 0"
|
test "`../../bin/dstar2tgba -D dsa.dstar --stats '%s %t %p %d'`" = "4 8 0 0"
|
||||||
|
test "`../../bin/dstar2tgba -DC dsa.dstar --stats '%s %t %p %d'`" = "5 11 1 0"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -213,7 +200,7 @@ Acc-Sig: +0 +1
|
||||||
4
|
4
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
run 0 ../ikwiad -XDD dra.dstar | tee stdout
|
run 0 ../ikwiad -XDB dra.dstar | tee stdout
|
||||||
|
|
||||||
cat >expected <<EOF
|
cat >expected <<EOF
|
||||||
digraph G {
|
digraph G {
|
||||||
|
|
@ -272,7 +259,7 @@ digraph G {
|
||||||
I [label="", style=invis, width=0]
|
I [label="", style=invis, width=0]
|
||||||
I -> 0
|
I -> 0
|
||||||
0 [label="0"]
|
0 [label="0"]
|
||||||
0 -> 0 [label="1"]
|
0 -> 0 [label="1\n{0}"]
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@
|
||||||
#include "twaalgos/dtbasat.hh"
|
#include "twaalgos/dtbasat.hh"
|
||||||
#include "twaalgos/dtgbasat.hh"
|
#include "twaalgos/dtgbasat.hh"
|
||||||
#include "twaalgos/stutter.hh"
|
#include "twaalgos/stutter.hh"
|
||||||
|
#include "twaalgos/totgba.hh"
|
||||||
|
|
||||||
#include "taalgos/tgba2ta.hh"
|
#include "taalgos/tgba2ta.hh"
|
||||||
#include "taalgos/dot.hh"
|
#include "taalgos/dot.hh"
|
||||||
|
|
@ -120,8 +121,6 @@ syntax(char* prog)
|
||||||
<< " ltl2dstar file" << std::endl
|
<< " ltl2dstar file" << std::endl
|
||||||
<< " -XDB read the from an ltl2dstar file and convert it to "
|
<< " -XDB read the from an ltl2dstar file and convert it to "
|
||||||
<< "TGBA" << std::endl
|
<< "TGBA" << std::endl
|
||||||
<< " -XDD read the from an ltl2dstar file and convert it to "
|
|
||||||
<< "TGBA,\n keeping it deterministic when possible\n"
|
|
||||||
<< " -XH do not compute an automaton, read it from a"
|
<< " -XH do not compute an automaton, read it from a"
|
||||||
<< " HOA file\n"
|
<< " HOA file\n"
|
||||||
<< " -XL do not compute an automaton, read it from an"
|
<< " -XL do not compute an automaton, read it from an"
|
||||||
|
|
@ -347,7 +346,6 @@ checked_main(int argc, char** argv)
|
||||||
bool from_file = false;
|
bool from_file = false;
|
||||||
enum { ReadDstar, ReadHoa } readformat = ReadHoa;
|
enum { ReadDstar, ReadHoa } readformat = ReadHoa;
|
||||||
bool nra2nba = false;
|
bool nra2nba = false;
|
||||||
bool dra2dba = false;
|
|
||||||
bool scc_filter = false;
|
bool scc_filter = false;
|
||||||
bool simpltl = false;
|
bool simpltl = false;
|
||||||
spot::ltl::ltl_simplifier_options redopt(false, false, false, false,
|
spot::ltl::ltl_simplifier_options redopt(false, false, false, false,
|
||||||
|
|
@ -876,13 +874,6 @@ checked_main(int argc, char** argv)
|
||||||
readformat = ReadDstar;
|
readformat = ReadDstar;
|
||||||
nra2nba = true;
|
nra2nba = true;
|
||||||
}
|
}
|
||||||
else if (!strcmp(argv[formula_index], "-XDD"))
|
|
||||||
{
|
|
||||||
from_file = true;
|
|
||||||
readformat = ReadDstar;
|
|
||||||
nra2nba = true;
|
|
||||||
dra2dba = true;
|
|
||||||
}
|
|
||||||
else if (!strcmp(argv[formula_index], "-XH"))
|
else if (!strcmp(argv[formula_index], "-XH"))
|
||||||
{
|
{
|
||||||
from_file = true;
|
from_file = true;
|
||||||
|
|
@ -986,20 +977,8 @@ checked_main(int argc, char** argv)
|
||||||
tm.start("dstar2tgba");
|
tm.start("dstar2tgba");
|
||||||
if (nra2nba)
|
if (nra2nba)
|
||||||
{
|
{
|
||||||
if (daut->type == spot::Rabin)
|
a = spot::to_generalized_buchi(daut->aut);
|
||||||
{
|
assume_sba = a->is_sba();
|
||||||
if (dra2dba)
|
|
||||||
a = spot::dstar_to_tgba(daut);
|
|
||||||
else
|
|
||||||
a = spot::nra_to_nba(daut);
|
|
||||||
assert(a->is_sba());
|
|
||||||
assume_sba = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
a = spot::nsa_to_tgba(daut);
|
|
||||||
assume_sba = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1112,6 +1091,9 @@ checked_main(int argc, char** argv)
|
||||||
if (scc_filter)
|
if (scc_filter)
|
||||||
{
|
{
|
||||||
tm.start("SCC-filter");
|
tm.start("SCC-filter");
|
||||||
|
if (a->has_state_based_acc() & !scc_filter_all)
|
||||||
|
a = spot::scc_filter_states(ensure_digraph(a));
|
||||||
|
else
|
||||||
a = spot::scc_filter(ensure_digraph(a), scc_filter_all);
|
a = spot::scc_filter(ensure_digraph(a), scc_filter_all);
|
||||||
tm.stop("SCC-filter");
|
tm.stop("SCC-filter");
|
||||||
assume_sba = false;
|
assume_sba = false;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue