Preliminirary support for generic acceptance.
* src/tgba/acc.hh: Add creation and printing of generic acceptance code. * src/tgba/acc.cc: New file. * src/tgba/Makefile.am: Add it. * src/tgbatest/acc.cc: More tests. * src/tgbatest/acc.test: Update. * src/tgba/tgba.hh (set_acceptance, get_acceptance): New methods. * src/tgba/tgbagraph.hh: Store acceptance code. * src/hoaparse/hoaparse.yy: Read any acceptance. * src/dstarparse/nsa2tgba.cc, src/ta/taexplicit.cc, src/tgba/tgbaproduct.cc, src/tgba/tgbasafracomplement.cc, src/tgbaalgos/degen.cc, src/tgbaalgos/hoa.cc, src/tgbaalgos/ltl2taa.cc, src/tgbaalgos/ltl2tgba_fm.cc, src/tgbaalgos/product.cc, src/tgbaalgos/stutter.cc, src/tgbatest/hoaparse.test: Adjust.
This commit is contained in:
parent
c61f053e2d
commit
fd1f6c4d61
19 changed files with 778 additions and 176 deletions
|
|
@ -199,6 +199,7 @@ namespace spot
|
|||
while (i != bs2num.end())
|
||||
delete (i++)->first.pend;
|
||||
|
||||
res->acc().set_generalized_buchi();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@
|
|||
spot::acc_cond::mark_t mark;
|
||||
pair* p;
|
||||
std::list<pair>* list;
|
||||
spot::acc_cond::acc_code* code;
|
||||
}
|
||||
|
||||
%code
|
||||
|
|
@ -201,6 +202,7 @@
|
|||
%type <p> nc-transition nc-src-dest
|
||||
%type <list> nc-transitions nc-transition-block
|
||||
%type <str> nc-one-ident nc-ident-list
|
||||
%type <code> acceptance-cond
|
||||
|
||||
/**** LBTT tokens *****/
|
||||
// Also using INT, STRING
|
||||
|
|
@ -216,6 +218,7 @@
|
|||
%destructor { delete $$; } <str>
|
||||
%destructor { bdd_delref($$); } <b>
|
||||
%destructor { bdd_delref($$->first); delete $$->second; delete $$; } <p>
|
||||
%destructor { delete $$; } <code>
|
||||
%destructor {
|
||||
for (std::list<pair>::iterator i = $$->begin();
|
||||
i != $$->end(); ++i)
|
||||
|
|
@ -484,7 +487,7 @@ header-item: "States:" INT
|
|||
}
|
||||
else
|
||||
{
|
||||
res.h->aut->set_acceptance_conditions($2);
|
||||
res.h->aut->acc().add_sets($2);
|
||||
res.accset = $2;
|
||||
res.accset_loc = @1 + @2;
|
||||
}
|
||||
|
|
@ -492,6 +495,8 @@ header-item: "States:" INT
|
|||
acceptance-cond
|
||||
{
|
||||
res.ignore_more_acc = true;
|
||||
res.h->aut->set_acceptance($2, *$4);
|
||||
delete $4;
|
||||
}
|
||||
| "acc-name:" IDENTIFIER acc-spec
|
||||
{
|
||||
|
|
@ -659,36 +664,65 @@ acc-set: INT
|
|||
|
||||
acceptance-cond: IDENTIFIER '(' acc-set ')'
|
||||
{
|
||||
if (!res.ignore_more_acc && *$1 != "Inf")
|
||||
error(@1, "this implementation only supports "
|
||||
"'Inf' acceptance");
|
||||
if ($3 != -1U)
|
||||
{
|
||||
res.pos_acc_sets |= res.h->aut->acc().mark($3);
|
||||
if (*$1 == "Inf")
|
||||
$$ = new spot::acc_cond::acc_code
|
||||
(res.h->aut->acc().inf({$3}));
|
||||
else
|
||||
$$ = new spot::acc_cond::acc_code
|
||||
(res.h->aut->acc().fin({$3}));
|
||||
}
|
||||
else
|
||||
{
|
||||
$$ = new spot::acc_cond::acc_code;
|
||||
}
|
||||
delete $1;
|
||||
}
|
||||
| IDENTIFIER '(' '!' acc-set ')'
|
||||
{
|
||||
if (!res.ignore_more_acc && *$1 != "Inf")
|
||||
error(@1, "this implementation only supports "
|
||||
"'Inf' acceptance");
|
||||
if ($4 != -1U)
|
||||
{
|
||||
res.neg_acc_sets |= res.h->aut->acc().mark($4);
|
||||
if (*$1 == "Inf")
|
||||
$$ = new spot::acc_cond::acc_code
|
||||
(res.h->aut->acc().inf_neg({$4}));
|
||||
else
|
||||
$$ = new spot::acc_cond::acc_code
|
||||
(res.h->aut->acc().fin_neg({$4}));
|
||||
}
|
||||
else
|
||||
{
|
||||
$$ = new spot::acc_cond::acc_code;
|
||||
}
|
||||
delete $1;
|
||||
}
|
||||
| '(' acceptance-cond ')'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| acceptance-cond '&' acceptance-cond
|
||||
{
|
||||
$3->append_and(std::move(*$1));
|
||||
$$ = $3;
|
||||
delete $1;
|
||||
}
|
||||
| acceptance-cond '|' acceptance-cond
|
||||
{
|
||||
if (!res.ignore_more_acc)
|
||||
error(@2, "this implementation does not support "
|
||||
"disjunction in acceptance conditions");
|
||||
$3->append_or(std::move(*$1));
|
||||
$$ = $3;
|
||||
delete $1;
|
||||
}
|
||||
| 't'
|
||||
{
|
||||
$$ = new spot::acc_cond::acc_code;
|
||||
}
|
||||
| 'f'
|
||||
{
|
||||
if (!res.ignore_more_acc)
|
||||
error(@$, "this implementation does not support "
|
||||
"false acceptance");
|
||||
{
|
||||
$$ = new spot::acc_cond::acc_code(res.h->aut->acc().fin({}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1213,7 +1247,10 @@ nc-transition:
|
|||
|
||||
lbtt: lbtt-header lbtt-body ENDAUT
|
||||
{
|
||||
res.pos_acc_sets = res.h->aut->acc().all_sets();
|
||||
auto& acc = res.h->aut->acc();
|
||||
unsigned num = acc.num_sets();
|
||||
res.h->aut->set_acceptance_conditions(num);
|
||||
res.pos_acc_sets = acc.all_sets();
|
||||
assert(!res.states_map.empty());
|
||||
auto n = res.states_map.size();
|
||||
if (n != (unsigned) res.states)
|
||||
|
|
@ -1380,28 +1417,108 @@ hoayy::parser::error(const location_type& location,
|
|||
error_list.emplace_back(location, message);
|
||||
}
|
||||
|
||||
static spot::acc_cond::acc_code
|
||||
fix_acceptance_aux(spot::acc_cond& acc,
|
||||
spot::acc_cond::acc_code in, unsigned pos,
|
||||
spot::acc_cond::mark_t onlyneg,
|
||||
spot::acc_cond::mark_t both,
|
||||
unsigned base)
|
||||
{
|
||||
auto& w = in[pos];
|
||||
switch (w.op)
|
||||
{
|
||||
case spot::acc_cond::acc_op::And:
|
||||
{
|
||||
unsigned sub = pos - w.size;
|
||||
--pos;
|
||||
auto c = fix_acceptance_aux(acc, in, pos, onlyneg, both, base);
|
||||
pos -= in[pos].size;
|
||||
while (sub < pos)
|
||||
{
|
||||
--pos;
|
||||
c.append_and(fix_acceptance_aux(acc, in, pos, onlyneg, both, base));
|
||||
pos -= in[pos].size;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
case spot::acc_cond::acc_op::Or:
|
||||
{
|
||||
unsigned sub = pos - w.size;
|
||||
--pos;
|
||||
auto c = fix_acceptance_aux(acc, in, pos, onlyneg, both, base);
|
||||
pos -= in[pos].size;
|
||||
while (sub < pos)
|
||||
{
|
||||
--pos;
|
||||
c.append_or(fix_acceptance_aux(acc, in, pos, onlyneg, both, base));
|
||||
pos -= in[pos].size;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
case spot::acc_cond::acc_op::Inf:
|
||||
return acc.inf(in[pos - 1].mark);
|
||||
case spot::acc_cond::acc_op::Fin:
|
||||
return acc.fin(in[pos - 1].mark);
|
||||
case spot::acc_cond::acc_op::FinNeg:
|
||||
{
|
||||
auto m = in[pos - 1].mark;
|
||||
auto c = acc.fin(onlyneg & m);
|
||||
spot::acc_cond::mark_t tmp = 0U;
|
||||
for (auto i: both.sets())
|
||||
{
|
||||
if (m.has(i))
|
||||
tmp.set(base);
|
||||
++base;
|
||||
}
|
||||
if (tmp)
|
||||
c.append_or(acc.fin(tmp));
|
||||
return c;
|
||||
}
|
||||
case spot::acc_cond::acc_op::InfNeg:
|
||||
{
|
||||
auto m = in[pos - 1].mark;
|
||||
auto c = acc.inf(onlyneg & m);
|
||||
spot::acc_cond::mark_t tmp = 0U;
|
||||
for (auto i: both.sets())
|
||||
{
|
||||
if (m.has(i))
|
||||
tmp.set(base);
|
||||
++base;
|
||||
}
|
||||
if (tmp)
|
||||
c.append_and(acc.inf(tmp));
|
||||
return c;
|
||||
}
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
static void fix_acceptance(result_& r)
|
||||
{
|
||||
auto& acc = r.h->aut->acc();
|
||||
// Compute the unused sets before possibly adding some below.
|
||||
auto unused = acc.comp(r.neg_acc_sets | r.pos_acc_sets);
|
||||
|
||||
// If a set x appears only as Inf(!x), we can complement it so that
|
||||
// we work with Inf(x) instead.
|
||||
if (auto onlyneg = r.neg_acc_sets - r.pos_acc_sets)
|
||||
auto onlyneg = r.neg_acc_sets - r.pos_acc_sets;
|
||||
if (onlyneg)
|
||||
{
|
||||
for (auto& t: r.h->aut->transition_vector())
|
||||
t.acc ^= onlyneg;
|
||||
}
|
||||
|
||||
// However if set x is used elsewhere, for instance in
|
||||
// Inf(!x) & Inf(x)
|
||||
// complementing x would be wrong. We need to create a
|
||||
// new set, y, that is the complement of x, and rewrite
|
||||
// this as Inf(y) & Inf(x).
|
||||
if (auto both = r.neg_acc_sets & r.pos_acc_sets)
|
||||
auto both = r.neg_acc_sets & r.pos_acc_sets;
|
||||
unsigned base = 0;
|
||||
if (both)
|
||||
{
|
||||
auto v = acc.sets(both);
|
||||
auto vs = v.size();
|
||||
unsigned base = acc.add_sets(vs);
|
||||
base = acc.add_sets(vs);
|
||||
for (auto& t: r.h->aut->transition_vector())
|
||||
if ((t.acc & both) != both)
|
||||
for (unsigned i = 0; i < vs; ++i)
|
||||
|
|
@ -1409,15 +1526,13 @@ static void fix_acceptance(result_& r)
|
|||
t.acc |= acc.mark(base + i);
|
||||
}
|
||||
|
||||
// Remove all acceptance sets that are not used in the acceptance
|
||||
// condition. Because the rest of the code still assume that all
|
||||
// acceptance sets have to be seen. See
|
||||
// https://github.com/adl/hoaf/issues/36
|
||||
if (unused)
|
||||
if (onlyneg || both)
|
||||
{
|
||||
for (auto& t: r.h->aut->transition_vector())
|
||||
t.acc = acc.strip(t.acc, unused);
|
||||
r.h->aut->set_acceptance_conditions(acc.num_sets() - unused.count());
|
||||
auto& acc = r.h->aut->acc();
|
||||
auto code = acc.get_acceptance();
|
||||
r.h->aut->set_acceptance(acc.num_sets(),
|
||||
fix_acceptance_aux(acc, code, code.size() - 1,
|
||||
onlyneg, both, base));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -359,6 +359,7 @@ namespace spot
|
|||
{
|
||||
get_dict()->register_all_variables_of(&tgba_, this);
|
||||
acc().add_sets(n_acc);
|
||||
acc().set_generalized_buchi();
|
||||
if (artificial_initial_state != 0)
|
||||
{
|
||||
state_ta_explicit* is = add_state(artificial_initial_state);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ tgba_HEADERS = \
|
|||
|
||||
noinst_LTLIBRARIES = libtgba.la
|
||||
libtgba_la_SOURCES = \
|
||||
acc.cc \
|
||||
bdddict.cc \
|
||||
bddprint.cc \
|
||||
formula2bdd.cc \
|
||||
|
|
|
|||
238
src/tgba/acc.cc
Normal file
238
src/tgba/acc.cc
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2015 Laboratoire de Recherche et Développement de
|
||||
// l'Epita.
|
||||
//
|
||||
// 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 <iostream>
|
||||
#include "acc.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
std::ostream& operator<<(std::ostream& os, spot::acc_cond::mark_t m)
|
||||
{
|
||||
auto a = m.id;
|
||||
os << '{';
|
||||
unsigned level = 0;
|
||||
const char* comma = "";
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
{
|
||||
os << comma << level;
|
||||
comma = ",";
|
||||
}
|
||||
a >>= 1;
|
||||
++level;
|
||||
}
|
||||
os << '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
static void
|
||||
print_code(std::ostream& os,
|
||||
const acc_cond::acc_code& code, unsigned pos)
|
||||
{
|
||||
const char* op = " | ";
|
||||
auto& w = code[pos];
|
||||
const char* negated = "";
|
||||
bool top = pos == code.size() - 1;
|
||||
switch (w.op)
|
||||
{
|
||||
case acc_cond::acc_op::And:
|
||||
op = " & ";
|
||||
case acc_cond::acc_op::Or:
|
||||
{
|
||||
unsigned sub = pos - w.size;
|
||||
if (!top)
|
||||
os << '(';
|
||||
bool first = true;
|
||||
while (sub < pos)
|
||||
{
|
||||
--pos;
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
os << op;
|
||||
print_code(os, code, pos);
|
||||
pos -= code[pos].size;
|
||||
}
|
||||
if (!top)
|
||||
os << ')';
|
||||
}
|
||||
break;
|
||||
case acc_cond::acc_op::InfNeg:
|
||||
negated = "!";
|
||||
case acc_cond::acc_op::Inf:
|
||||
{
|
||||
auto a = code[pos - 1].mark.id;
|
||||
if (a == 0U)
|
||||
{
|
||||
os << 't';
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned level = 0;
|
||||
const char* and_ = "";
|
||||
if (!top)
|
||||
os << '(';
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
{
|
||||
os << and_ << "Inf(" << negated << level << ')';
|
||||
and_ = "&";
|
||||
}
|
||||
a >>= 1;
|
||||
++level;
|
||||
}
|
||||
if (!top)
|
||||
os << ')';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case acc_cond::acc_op::FinNeg:
|
||||
negated = "!";
|
||||
case acc_cond::acc_op::Fin:
|
||||
{
|
||||
auto a = code[pos - 1].mark.id;
|
||||
if (a == 0U)
|
||||
{
|
||||
os << 'f';
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned level = 0;
|
||||
const char* or_ = "";
|
||||
if (!top)
|
||||
os << '(';
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
{
|
||||
os << or_ << "Fin(" << negated << level << ')';
|
||||
or_ = "|";
|
||||
}
|
||||
a >>= 1;
|
||||
++level;
|
||||
}
|
||||
if (!top)
|
||||
os << ')';
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
eval(acc_cond::mark_t inf, acc_cond::mark_t fin,
|
||||
const acc_cond::acc_code& code, unsigned pos)
|
||||
{
|
||||
auto& w = code[pos];
|
||||
switch (w.op)
|
||||
{
|
||||
case acc_cond::acc_op::And:
|
||||
{
|
||||
unsigned sub = pos - w.size;
|
||||
while (sub < pos)
|
||||
{
|
||||
--pos;
|
||||
if (!eval(inf, fin, code, pos))
|
||||
return false;
|
||||
pos -= code[pos].size;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case acc_cond::acc_op::Or:
|
||||
{
|
||||
unsigned sub = pos - w.size;
|
||||
while (sub < pos)
|
||||
{
|
||||
--pos;
|
||||
if (eval(inf, fin, code, pos))
|
||||
return true;
|
||||
pos -= code[pos].size;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case acc_cond::acc_op::Inf:
|
||||
return (code[pos - 1].mark & inf) == code[pos - 1].mark;
|
||||
case acc_cond::acc_op::Fin:
|
||||
return (code[pos - 1].mark & fin) != 0U;
|
||||
case acc_cond::acc_op::FinNeg:
|
||||
case acc_cond::acc_op::InfNeg:
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool acc_cond::accepting(mark_t inf, mark_t fin) const
|
||||
{
|
||||
if (code_.empty())
|
||||
return true;
|
||||
return eval(inf, fin, code_, code_.size() - 1);
|
||||
}
|
||||
|
||||
bool acc_cond::accepting(mark_t inf) const
|
||||
{
|
||||
if (uses_fin_acceptance())
|
||||
throw std::runtime_error
|
||||
("Fin acceptance is not supported by this code path.");
|
||||
return accepting(inf, 0U);
|
||||
}
|
||||
|
||||
bool acc_cond::check_fin_acceptance() const
|
||||
{
|
||||
if (code_.empty())
|
||||
return false;
|
||||
unsigned pos = code_.size();
|
||||
do
|
||||
{
|
||||
switch (code_[pos - 1].op)
|
||||
{
|
||||
case acc_cond::acc_op::And:
|
||||
case acc_cond::acc_op::Or:
|
||||
--pos;
|
||||
break;
|
||||
case acc_cond::acc_op::Inf:
|
||||
case acc_cond::acc_op::InfNeg:
|
||||
pos -= 2;
|
||||
break;
|
||||
case acc_cond::acc_op::Fin:
|
||||
case acc_cond::acc_op::FinNeg:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
while (pos > 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os,
|
||||
const spot::acc_cond::acc_code& code)
|
||||
{
|
||||
if (code.empty())
|
||||
os << 't';
|
||||
else
|
||||
print_code(os, code, code.size() - 1);
|
||||
return os;
|
||||
}
|
||||
}
|
||||
309
src/tgba/acc.hh
309
src/tgba/acc.hh
|
|
@ -25,10 +25,11 @@
|
|||
# include <sstream>
|
||||
# include <vector>
|
||||
# include "ltlenv/defaultenv.hh"
|
||||
# include <iostream>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
class acc_cond
|
||||
class SPOT_API acc_cond
|
||||
{
|
||||
public:
|
||||
struct mark_t
|
||||
|
|
@ -90,7 +91,6 @@ namespace spot
|
|||
return id != 0;
|
||||
}
|
||||
|
||||
|
||||
bool has(unsigned u) const
|
||||
{
|
||||
return id & (1U << u);
|
||||
|
|
@ -170,25 +170,142 @@ namespace spot
|
|||
return *this;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, mark_t m)
|
||||
template<class iterator>
|
||||
void fill(iterator here) const
|
||||
{
|
||||
auto a = m.id;
|
||||
os << '{';
|
||||
auto a = id;
|
||||
unsigned level = 0;
|
||||
const char* comma = "";
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
{
|
||||
os << comma << level;
|
||||
comma = ",";
|
||||
}
|
||||
a >>= 1;
|
||||
*here++ = level;
|
||||
++level;
|
||||
a >>= 1;
|
||||
}
|
||||
os << '}';
|
||||
return os;
|
||||
}
|
||||
|
||||
// FIXME: Return some iterable object without building a vector.
|
||||
std::vector<unsigned> sets() const
|
||||
{
|
||||
std::vector<unsigned> res;
|
||||
fill(std::back_inserter(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
SPOT_API
|
||||
friend std::ostream& operator<<(std::ostream& os, mark_t m);
|
||||
};
|
||||
|
||||
// This encodes either an operator or set of acceptance sets.
|
||||
enum class acc_op : unsigned char
|
||||
{ Inf, Fin, InfNeg, FinNeg, And, Or };
|
||||
union acc_word
|
||||
{
|
||||
mark_t mark;
|
||||
struct {
|
||||
acc_op op; // Operator
|
||||
unsigned char size; // Size of the subtree (number of acc_word),
|
||||
// not counting this node.
|
||||
};
|
||||
};
|
||||
|
||||
struct acc_code: public std::vector<acc_word>
|
||||
{
|
||||
bool is_true() const
|
||||
{
|
||||
unsigned s = size();
|
||||
return s == 0
|
||||
|| ((*this)[s - 1].op == acc_op::Inf && (*this)[s - 2].mark == 0U);
|
||||
}
|
||||
|
||||
bool is_false() const
|
||||
{
|
||||
unsigned s = size();
|
||||
return s > 1
|
||||
&& (*this)[s - 1].op == acc_op::Fin && (*this)[s - 2].mark == 0U;
|
||||
}
|
||||
|
||||
void append_and(acc_code&& r)
|
||||
{
|
||||
if (is_true() || r.is_false())
|
||||
{
|
||||
*this = std::move(r);
|
||||
return;
|
||||
}
|
||||
if (is_false() || r.is_true())
|
||||
return;
|
||||
unsigned s = size() - 1;
|
||||
unsigned rs = r.size() - 1;
|
||||
// Inf(a) & Inf(b) = Inf(a & b)
|
||||
if (((*this)[s].op == acc_op::Inf && r[rs].op == acc_op::Inf)
|
||||
|| ((*this)[s].op == acc_op::InfNeg && r[rs].op == acc_op::InfNeg))
|
||||
{
|
||||
(*this)[s - 1].mark |= r[rs - 1].mark;
|
||||
return;
|
||||
}
|
||||
if ((*this)[s].op == acc_op::And)
|
||||
pop_back();
|
||||
insert(this->end(), r.begin(), r.end());
|
||||
acc_word w;
|
||||
w.op = acc_op::And;
|
||||
w.size = size();
|
||||
push_back(w);
|
||||
}
|
||||
|
||||
void append_or(acc_code&& r)
|
||||
{
|
||||
if (is_true() || r.is_false())
|
||||
return;
|
||||
if (is_false() || r.is_true())
|
||||
{
|
||||
*this = std::move(r);
|
||||
return;
|
||||
}
|
||||
unsigned s = size() - 1;
|
||||
unsigned rs = r.size() - 1;
|
||||
// Fin(a) | Fin(b) = Fin(a | b)
|
||||
if (((*this)[s].op == acc_op::Fin && r[rs].op == acc_op::Fin)
|
||||
|| ((*this)[s].op == acc_op::FinNeg && r[rs].op == acc_op::FinNeg))
|
||||
{
|
||||
(*this)[s - 1].mark |= r[rs - 1].mark;
|
||||
return;
|
||||
}
|
||||
if ((*this)[s].op == acc_op::Or)
|
||||
pop_back();
|
||||
insert(this->end(), r.begin(), r.end());
|
||||
acc_word w;
|
||||
w.op = acc_op::Or;
|
||||
w.size = size();
|
||||
push_back(w);
|
||||
}
|
||||
|
||||
void shift_left(unsigned sets)
|
||||
{
|
||||
if (empty())
|
||||
return;
|
||||
unsigned pos = size();
|
||||
do
|
||||
{
|
||||
switch ((*this)[pos - 1].op)
|
||||
{
|
||||
case acc_cond::acc_op::And:
|
||||
case acc_cond::acc_op::Or:
|
||||
--pos;
|
||||
break;
|
||||
case acc_cond::acc_op::Inf:
|
||||
case acc_cond::acc_op::InfNeg:
|
||||
case acc_cond::acc_op::Fin:
|
||||
case acc_cond::acc_op::FinNeg:
|
||||
pos -= 2;
|
||||
(*this)[pos].mark.id <<= sets;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (pos > 0);
|
||||
}
|
||||
|
||||
SPOT_API
|
||||
friend std::ostream& operator<<(std::ostream& os, const acc_code& code);
|
||||
};
|
||||
|
||||
acc_cond(unsigned n_sets = 0)
|
||||
|
|
@ -198,7 +315,7 @@ namespace spot
|
|||
}
|
||||
|
||||
acc_cond(const acc_cond& o)
|
||||
: num_(o.num_), all_(o.all_)
|
||||
: num_(o.num_), all_(o.all_), code_(o.code_)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -206,6 +323,91 @@ namespace spot
|
|||
{
|
||||
}
|
||||
|
||||
void set_acceptance(const acc_code& code)
|
||||
{
|
||||
code_ = code;
|
||||
uses_fin_acceptance_ = check_fin_acceptance();
|
||||
}
|
||||
|
||||
acc_code get_acceptance() const
|
||||
{
|
||||
return code_;
|
||||
}
|
||||
|
||||
bool uses_fin_acceptance() const
|
||||
{
|
||||
return uses_fin_acceptance_;
|
||||
}
|
||||
|
||||
void set_generalized_buchi()
|
||||
{
|
||||
set_acceptance(inf(all_sets()));
|
||||
}
|
||||
|
||||
bool is_generalized_buchi() const
|
||||
{
|
||||
unsigned s = code_.size();
|
||||
return (s == 0 && num_ == 0) ||
|
||||
(s == 2 && code_[1].op == acc_op::Inf && code_[0].mark == all_sets());
|
||||
}
|
||||
|
||||
protected:
|
||||
bool check_fin_acceptance() const;
|
||||
|
||||
acc_code primitive(mark_t mark, acc_op op) const
|
||||
{
|
||||
acc_word w1;
|
||||
w1.mark = mark;
|
||||
acc_word w2;
|
||||
w2.op = op;
|
||||
w2.size = 1;
|
||||
acc_code c;
|
||||
c.push_back(w1);
|
||||
c.push_back(w2);
|
||||
return c;
|
||||
}
|
||||
|
||||
public:
|
||||
acc_code inf(mark_t mark) const
|
||||
{
|
||||
return primitive(mark, acc_op::Inf);
|
||||
}
|
||||
|
||||
acc_code inf(std::initializer_list<unsigned> vals) const
|
||||
{
|
||||
return inf(marks(vals.begin(), vals.end()));
|
||||
}
|
||||
|
||||
acc_code inf_neg(mark_t mark) const
|
||||
{
|
||||
return primitive(mark, acc_op::InfNeg);
|
||||
}
|
||||
|
||||
acc_code inf_neg(std::initializer_list<unsigned> vals) const
|
||||
{
|
||||
return inf_neg(marks(vals.begin(), vals.end()));
|
||||
}
|
||||
|
||||
acc_code fin(mark_t mark) const
|
||||
{
|
||||
return primitive(mark, acc_op::Fin);
|
||||
}
|
||||
|
||||
acc_code fin(std::initializer_list<unsigned> vals) const
|
||||
{
|
||||
return fin(marks(vals.begin(), vals.end()));
|
||||
}
|
||||
|
||||
acc_code fin_neg(mark_t mark) const
|
||||
{
|
||||
return primitive(mark, acc_op::FinNeg);
|
||||
}
|
||||
|
||||
acc_code fin_neg(std::initializer_list<unsigned> vals) const
|
||||
{
|
||||
return fin_neg(marks(vals.begin(), vals.end()));
|
||||
}
|
||||
|
||||
unsigned add_sets(unsigned num)
|
||||
{
|
||||
if (num == 0)
|
||||
|
|
@ -225,7 +427,7 @@ namespace spot
|
|||
|
||||
mark_t mark(unsigned u) const
|
||||
{
|
||||
return out(mark_(u));
|
||||
return mark_(u);
|
||||
}
|
||||
|
||||
template<class iterator>
|
||||
|
|
@ -234,7 +436,7 @@ namespace spot
|
|||
mark_t::value_t res = 0U;
|
||||
for (iterator i = begin; i != end; ++i)
|
||||
res |= mark_(*i);
|
||||
return out(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
mark_t marks(std::initializer_list<unsigned> vals) const
|
||||
|
|
@ -242,27 +444,10 @@ namespace spot
|
|||
return marks(vals.begin(), vals.end());
|
||||
}
|
||||
|
||||
template<class iterator>
|
||||
void fill_from(mark_t m, iterator here) const
|
||||
{
|
||||
auto a = in(m);
|
||||
unsigned level = 0;
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
*here++ = level;
|
||||
++level;
|
||||
a >>= 1;
|
||||
}
|
||||
assert(level <= num_sets());
|
||||
}
|
||||
|
||||
// FIXME: Return some iterable object without building a vector.
|
||||
std::vector<unsigned> sets(mark_t m) const
|
||||
{
|
||||
std::vector<unsigned> res;
|
||||
fill_from(m, std::back_inserter(res));
|
||||
return res;
|
||||
return m.sets();
|
||||
}
|
||||
|
||||
// whether m contains u
|
||||
|
|
@ -290,47 +475,27 @@ namespace spot
|
|||
const acc_cond& ra, mark_t rm) const
|
||||
{
|
||||
assert(la.num_sets() + ra.num_sets() == num_sets());
|
||||
return la.in(lm) | (ra.in(rm) << la.num_sets());
|
||||
(void)ra;
|
||||
return lm.id | (rm.id << la.num_sets());
|
||||
}
|
||||
|
||||
mark_t comp(mark_t l) const
|
||||
{
|
||||
return out(all_ ^ in(l));
|
||||
return all_ ^ l.id;
|
||||
}
|
||||
|
||||
mark_t all_sets() const
|
||||
{
|
||||
return out(all_);
|
||||
return all_;
|
||||
}
|
||||
|
||||
bool accepting(mark_t inf) const
|
||||
{
|
||||
return in(inf) == all_;
|
||||
}
|
||||
bool accepting(mark_t inf, mark_t fin) const;
|
||||
|
||||
std::ostream& format_quoted(std::ostream& os, mark_t m) const
|
||||
{
|
||||
auto a = in(m);
|
||||
if (a == 0U)
|
||||
return os;
|
||||
unsigned level = 0;
|
||||
const char* space = "";
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
{
|
||||
os << space << '"' << level << '"';
|
||||
space = " ";
|
||||
}
|
||||
a >>= 1;
|
||||
++level;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
bool accepting(mark_t inf) const;
|
||||
|
||||
std::ostream& format(std::ostream& os, mark_t m) const
|
||||
{
|
||||
auto a = in(m);
|
||||
auto a = m;
|
||||
if (a == 0U)
|
||||
return os;
|
||||
return os << m;
|
||||
|
|
@ -360,7 +525,7 @@ namespace spot
|
|||
unsigned all = all_ ^ (u | (1 << x));
|
||||
for (iterator y = begin; y != end; ++y)
|
||||
{
|
||||
auto v = in(*y);
|
||||
auto v = y->id;
|
||||
if (v & (1 << x))
|
||||
{
|
||||
all &= v;
|
||||
|
|
@ -370,7 +535,7 @@ namespace spot
|
|||
}
|
||||
u |= all;
|
||||
}
|
||||
return out(u);
|
||||
return u;
|
||||
}
|
||||
|
||||
mark_t strip(mark_t x, mark_t y) const
|
||||
|
|
@ -381,8 +546,8 @@ namespace spot
|
|||
// == 10 1 11 100
|
||||
// == 10111100
|
||||
|
||||
auto xv = in(x); // 100101110100
|
||||
auto yv = in(y); // 001011001000
|
||||
auto xv = x.id; // 100101110100
|
||||
auto yv = y.id; // 001011001000
|
||||
|
||||
while (yv && xv)
|
||||
{
|
||||
|
|
@ -394,7 +559,7 @@ namespace spot
|
|||
yv = (yv & lm) >> 1;
|
||||
}
|
||||
|
||||
return out(xv);
|
||||
return xv;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -411,18 +576,10 @@ namespace spot
|
|||
return -1U >> (8 * sizeof(mark_t::value_t) - num_);
|
||||
}
|
||||
|
||||
mark_t::value_t in(mark_t m) const
|
||||
{
|
||||
return m.id;
|
||||
}
|
||||
|
||||
mark_t out(mark_t::value_t r) const
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned num_;
|
||||
mark_t::value_t all_;
|
||||
acc_code code_;
|
||||
bool uses_fin_acceptance_ = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -638,6 +638,25 @@ namespace spot
|
|||
protected:
|
||||
acc_cond acc_;
|
||||
|
||||
public:
|
||||
auto get_acceptance() const
|
||||
SPOT_RETURN(acc_.get_acceptance());
|
||||
|
||||
void set_acceptance(unsigned num, const acc_cond::acc_code& c)
|
||||
{
|
||||
if (num < acc_.num_sets())
|
||||
{
|
||||
acc_.~acc_cond();
|
||||
new (&acc_) acc_cond;
|
||||
}
|
||||
acc_.add_sets(num - acc_.num_sets());
|
||||
acc_.set_acceptance(c);
|
||||
prop_single_acc_set(!acc_.uses_fin_acceptance() && num == 1);
|
||||
if (num == 0)
|
||||
prop_state_based_acc();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Do the actual computation of tgba::support_conditions().
|
||||
virtual bdd compute_support_conditions(const state* state) const = 0;
|
||||
mutable const state* last_support_conditions_input_;
|
||||
|
|
|
|||
|
|
@ -334,6 +334,7 @@ namespace spot
|
|||
return g_.trans_data(t);
|
||||
}
|
||||
|
||||
// FIXME: Should be renamed as set_generalized_buchi()
|
||||
void set_acceptance_conditions(unsigned num)
|
||||
{
|
||||
if (num < acc_.num_sets())
|
||||
|
|
@ -342,9 +343,10 @@ namespace spot
|
|||
new (&acc_) acc_cond;
|
||||
}
|
||||
acc_.add_sets(num - acc_.num_sets());
|
||||
prop_single_acc_set(num == 1);
|
||||
prop_single_acc_set(!acc_.uses_fin_acceptance() && num == 1);
|
||||
if (num == 0)
|
||||
prop_state_based_acc();
|
||||
acc_.set_generalized_buchi();
|
||||
}
|
||||
|
||||
acc_cond::mark_t set_single_acceptance_set()
|
||||
|
|
@ -429,7 +431,12 @@ namespace spot
|
|||
/// \brief Copy the acceptance conditions of another tgba.
|
||||
void copy_acceptance_conditions_of(const const_tgba_ptr& a)
|
||||
{
|
||||
set_acceptance_conditions(a->acc().num_sets());
|
||||
// FIXME: Should rename as copy_acceptance_condition*_of
|
||||
acc_ = a->acc();
|
||||
unsigned num = acc_.num_sets();
|
||||
prop_single_acc_set(!acc_.uses_fin_acceptance() && num == 1);
|
||||
if (num == 0)
|
||||
prop_state_based_acc();
|
||||
}
|
||||
|
||||
void copy_ap_of(const const_tgba_ptr& a)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2009, 2011, 2012, 2014 Laboratoire de Recherche et
|
||||
// Copyright (C) 2009, 2011, 2012, 2014, 2015 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
// Copyright (C) 2003, 2004, 2006 Laboratoire d'Informatique de
|
||||
// Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
|
||||
|
|
@ -311,7 +311,11 @@ namespace spot
|
|||
d->register_all_propositions_of(&right_, this);
|
||||
|
||||
assert(acc_.num_sets() == 0);
|
||||
acc_.add_sets(left->acc().num_sets() + right->acc().num_sets());
|
||||
auto left_num = left->acc().num_sets();
|
||||
auto right_acc = right->get_acceptance();
|
||||
right_acc.shift_left(left_num);
|
||||
right_acc.append_and(left->get_acceptance());
|
||||
set_acceptance(left_num + right->acc().num_sets(), right_acc);
|
||||
}
|
||||
|
||||
tgba_product::~tgba_product()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Laboratoire de
|
||||
// Recherche et Développement de l'Epita (LRDE).
|
||||
// Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Laboratoire
|
||||
// de Recherche et Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -1091,6 +1091,7 @@ namespace spot
|
|||
for (unsigned i = 0; i < nb_acc; ++i)
|
||||
acceptance_cond_vec_.push_back(acc_.mark(acc_.add_set()));
|
||||
#endif
|
||||
acc_.set_generalized_buchi();
|
||||
}
|
||||
|
||||
tgba_safra_complement::~tgba_safra_complement()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2012, 2013, 2014 Laboratoire de Recherche et
|
||||
// Copyright (C) 2012, 2013, 2014, 2015 Laboratoire de Recherche et
|
||||
// Développement de l'Epita.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
|
|
@ -128,13 +128,12 @@ namespace spot
|
|||
|
||||
public:
|
||||
unsigned
|
||||
next_level(const acc_cond& acc, int slevel,
|
||||
acc_cond::mark_t set, bool skip_levels)
|
||||
next_level(int slevel, acc_cond::mark_t set, bool skip_levels)
|
||||
{
|
||||
// Update the order with any new set we discover
|
||||
if (auto newsets = set - found_)
|
||||
{
|
||||
acc.fill_from(newsets, std::back_inserter(order_));
|
||||
newsets.fill(std::back_inserter(order_));
|
||||
found_ |= newsets;
|
||||
}
|
||||
|
||||
|
|
@ -161,20 +160,19 @@ namespace spot
|
|||
// Accepting order for each SCC
|
||||
class scc_orders
|
||||
{
|
||||
const acc_cond& acc_;
|
||||
std::map<int, acc_order> orders_;
|
||||
bool skip_levels_;
|
||||
|
||||
public:
|
||||
scc_orders(const acc_cond& acc, bool skip_levels):
|
||||
acc_(acc), skip_levels_(skip_levels)
|
||||
scc_orders(bool skip_levels):
|
||||
skip_levels_(skip_levels)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned
|
||||
next_level(int scc, int slevel, acc_cond::mark_t set)
|
||||
{
|
||||
return orders_[scc].next_level(acc_, slevel, set, skip_levels_);
|
||||
return orders_[scc].next_level(slevel, set, skip_levels_);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -226,7 +224,7 @@ namespace spot
|
|||
}
|
||||
|
||||
// Initialize scc_orders
|
||||
scc_orders orders(a->acc(), skip_levels);
|
||||
scc_orders orders(skip_levels);
|
||||
|
||||
// and vice-versa.
|
||||
ds2num_map ds2num;
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@ namespace spot
|
|||
}
|
||||
os << nl;
|
||||
unsigned num_acc = aut->acc().num_sets();
|
||||
if (aut->acc().is_generalized_buchi())
|
||||
{
|
||||
if (num_acc == 0)
|
||||
os << "acc-name: all";
|
||||
else if (num_acc == 1)
|
||||
|
|
@ -259,18 +261,9 @@ namespace spot
|
|||
else
|
||||
os << "acc-name: generalized-Buchi " << num_acc;
|
||||
os << nl;
|
||||
os << "Acceptance: " << num_acc;
|
||||
if (num_acc > 0)
|
||||
{
|
||||
os << " Inf(0";
|
||||
for (unsigned i = 1; i < num_acc; ++i)
|
||||
os << ")&Inf(" << i;
|
||||
os << ')';
|
||||
}
|
||||
else
|
||||
{
|
||||
os << " t";
|
||||
}
|
||||
os << "Acceptance: " << num_acc << ' ';
|
||||
os << aut->acc().get_acceptance();
|
||||
os << nl;
|
||||
os << "properties: trans-labels explicit-labels";
|
||||
if (acceptance == Hoa_Acceptance_States)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2009, 2010, 2012, 2013, 2014 Laboratoire de Recherche
|
||||
// et Développement de l'Epita (LRDE).
|
||||
// Copyright (C) 2009, 2010, 2012, 2013, 2014, 2015 Laboratoire de
|
||||
// Recherche et Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -423,6 +423,7 @@ namespace spot
|
|||
auto taa = v.result(); // Careful: before the destroy!
|
||||
f2->destroy();
|
||||
delete lcc;
|
||||
taa->acc().set_generalized_buchi();
|
||||
return taa;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2505,10 +2505,14 @@ namespace spot
|
|||
|
||||
dict->register_propositions(fc.used_vars(), a);
|
||||
|
||||
auto& acc = a->acc();
|
||||
|
||||
unsigned ns = a->num_states();
|
||||
for (unsigned s = 0; s < ns; ++s)
|
||||
for (auto& t: a->out(s))
|
||||
t.acc = a->acc().comp(t.acc);
|
||||
t.acc = acc.comp(t.acc);
|
||||
|
||||
acc.set_generalized_buchi();
|
||||
|
||||
if (!simplifier)
|
||||
// This should not be deleted before we have registered all propositions.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2014 Laboratoire de Recherche et
|
||||
// Copyright (C) 2014, 2015 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
|
|
@ -52,8 +52,11 @@ namespace spot
|
|||
auto res = make_tgba_digraph(left->get_dict());
|
||||
res->copy_ap_of(left);
|
||||
res->copy_ap_of(right);
|
||||
res->set_acceptance_conditions(left->acc().num_sets()
|
||||
+ right->acc().num_sets());
|
||||
auto left_num = left->acc().num_sets();
|
||||
auto right_acc = right->get_acceptance();
|
||||
right_acc.shift_left(left_num);
|
||||
right_acc.append_and(left->get_acceptance());
|
||||
res->set_acceptance(left_num + right->acc().num_sets(), right_acc);
|
||||
|
||||
auto v = new product_states;
|
||||
res->set_named_prop("product-states", v);
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ namespace spot
|
|||
get_dict()->register_all_propositions_of(&a_, this);
|
||||
assert(acc_.num_sets() == 0);
|
||||
acc_.add_sets(a_->acc().num_sets());
|
||||
acc_.set_generalized_buchi();
|
||||
}
|
||||
|
||||
virtual ~tgbasl()
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ void check(spot::acc_cond& ac, spot::acc_cond::mark_t m)
|
|||
int main()
|
||||
{
|
||||
spot::acc_cond ac(4);
|
||||
ac.set_generalized_buchi();
|
||||
std::cout << ac.get_acceptance() << '\n';
|
||||
|
||||
auto m1 = ac.marks({0, 2});
|
||||
auto m2 = ac.marks({0, 3});
|
||||
|
|
@ -50,6 +52,7 @@ int main()
|
|||
check(ac, m1 | m2 | m3);
|
||||
|
||||
ac.add_set();
|
||||
ac.set_generalized_buchi();
|
||||
|
||||
check(ac, m1);
|
||||
check(ac, m2);
|
||||
|
|
@ -62,9 +65,11 @@ int main()
|
|||
check(ac, ac.comp(m2 & m3));
|
||||
|
||||
spot::acc_cond ac2(ac.num_sets());
|
||||
ac2.set_generalized_buchi();
|
||||
check(ac2, m3);
|
||||
|
||||
spot::acc_cond ac3(ac.num_sets() + ac2.num_sets());
|
||||
ac3.set_generalized_buchi();
|
||||
std::cout << ac.num_sets() << " + "
|
||||
<< ac2.num_sets() << " = " << ac3.num_sets() << '\n';
|
||||
auto m5 = ac3.join(ac, m2, ac2, m3);
|
||||
|
|
@ -74,10 +79,8 @@ int main()
|
|||
auto m7 = ac3.join(ac, ac.comp(m2 & m3), ac2, ac2.all_sets());
|
||||
check(ac3, m7);
|
||||
|
||||
std::vector<unsigned> v;
|
||||
ac3.fill_from(m7, std::back_inserter(v));
|
||||
const char* comma = "";
|
||||
for (auto i: v)
|
||||
for (auto i: m7.sets())
|
||||
{
|
||||
std::cout << comma << i;
|
||||
comma = ",";
|
||||
|
|
@ -85,6 +88,7 @@ int main()
|
|||
std::cout << '\n';
|
||||
|
||||
spot::acc_cond ac4;
|
||||
ac4.set_generalized_buchi();
|
||||
check(ac4, ac4.all_sets());
|
||||
check(ac4, ac4.comp(ac4.all_sets()));
|
||||
|
||||
|
|
@ -102,4 +106,17 @@ int main()
|
|||
check(ac, ac.strip(v, u));
|
||||
}
|
||||
|
||||
|
||||
auto code1 = ac.inf({0, 1, 3});
|
||||
std::cout << code1.size() << ' ' << code1 << '\n';
|
||||
code1.append_or(ac.fin({2}));
|
||||
std::cout << code1.size() << ' ' << code1 << '\n';
|
||||
code1.append_or(ac.fin({0}));
|
||||
std::cout << code1.size() << ' ' << code1 << '\n';
|
||||
code1.append_or(ac.fin({}));
|
||||
std::cout << code1.size() << ' ' << code1 << '\n';
|
||||
code1.append_and(ac.inf({}));
|
||||
std::cout << code1.size() << ' ' << code1 << '\n';
|
||||
code1.append_and(ac.fin({}));
|
||||
std::cout << code1.size() << ' ' << code1 << '\n';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
set -e
|
||||
|
||||
cat >expect <<EOF
|
||||
Inf(0)&Inf(1)&Inf(2)&Inf(3)
|
||||
#2: {0,2}
|
||||
#2: {0,3}
|
||||
#2: {1,2}
|
||||
|
|
@ -58,6 +59,12 @@ stripping
|
|||
#1: {0}
|
||||
#1: {4}
|
||||
#1: {2}
|
||||
2 Inf(0)&Inf(1)&Inf(3)
|
||||
5 (Fin(2)) | (Inf(0)&Inf(1)&Inf(3))
|
||||
7 (Fin(0)) | (Fin(2)) | (Inf(0)&Inf(1)&Inf(3))
|
||||
7 (Fin(0)) | (Fin(2)) | (Inf(0)&Inf(1)&Inf(3))
|
||||
7 (Fin(0)) | (Fin(2)) | (Inf(0)&Inf(1)&Inf(3))
|
||||
2 f
|
||||
EOF
|
||||
|
||||
run 0 ../acc | tee stdout
|
||||
|
|
|
|||
|
|
@ -1321,9 +1321,6 @@ EOF
|
|||
# Acceptance: 1 Inf(0)
|
||||
# and a development version of our parser would
|
||||
# incorrectly interpret the former as the latter.
|
||||
#
|
||||
# Make sure we ignore all {0} if the acceptance is "1 t".
|
||||
# See https://github.com/adl/hoaf/issues/36
|
||||
|
||||
cat >input <<EOF
|
||||
HOA: v1
|
||||
|
|
@ -1362,46 +1359,83 @@ State: 0
|
|||
--END--
|
||||
EOF
|
||||
|
||||
# The mapping of acceptance sets for the second automaton is
|
||||
# input -> output
|
||||
# 0 -> 0
|
||||
# 1 -> removed
|
||||
# 2 -> 1
|
||||
# 3 -> removed
|
||||
# 4 -> 2
|
||||
# !2 -> 3
|
||||
expectok input <<EOF
|
||||
expectok input -v --is-empty <<EOF
|
||||
HOA: v1
|
||||
name: "TGBA for Fa"
|
||||
States: 2
|
||||
Start: 0
|
||||
AP: 1 "a"
|
||||
acc-name: all
|
||||
Acceptance: 0 t
|
||||
properties: trans-labels explicit-labels state-acc complete deterministic
|
||||
Acceptance: 1 t
|
||||
properties: trans-labels explicit-labels trans-acc complete deterministic
|
||||
--BODY--
|
||||
State: 0 "F(a)"
|
||||
[0] 1
|
||||
[0] 1 {0}
|
||||
[!0] 0
|
||||
State: 1 "t"
|
||||
[t] 1
|
||||
[t] 1 {0}
|
||||
--END--
|
||||
HOA: v1
|
||||
States: 1
|
||||
Start: 0
|
||||
AP: 3 "a" "b" "c"
|
||||
acc-name: generalized-Buchi 4
|
||||
Acceptance: 4 Inf(0)&Inf(1)&Inf(2)&Inf(3)
|
||||
Acceptance: 6 Inf(0)&Inf(2)&Inf(4)&Inf(5)
|
||||
properties: trans-labels explicit-labels trans-acc complete deterministic
|
||||
--BODY--
|
||||
State: 0
|
||||
[0&1&2] 0 {0 1 2}
|
||||
[!0&1&2] 0 {1 2}
|
||||
[0&!1&2] 0 {0 1}
|
||||
[!0&!1&2] 0 {1}
|
||||
[0&1&!2] 0 {0 2 3}
|
||||
[!0&1&!2] 0 {2 3}
|
||||
[0&!1&!2] 0 {0 3}
|
||||
[!0&!1&!2] 0 {3}
|
||||
[0&1&2] 0 {0 2 4}
|
||||
[!0&1&2] 0 {2 4}
|
||||
[0&!1&2] 0 {0 2}
|
||||
[!0&!1&2] 0 {2}
|
||||
[0&1&!2] 0 {0 4 5}
|
||||
[!0&1&!2] 0 {4 5}
|
||||
[0&!1&!2] 0 {0 5}
|
||||
[!0&!1&!2] 0 {5}
|
||||
--END--
|
||||
EOF
|
||||
|
||||
|
||||
# FIXME: Test removal of useless acceptance sets
|
||||
#
|
||||
# # The mapping of acceptance sets for the second automaton is
|
||||
# # input -> output
|
||||
# # 0 -> 0
|
||||
# # 1 -> removed
|
||||
# # 2 -> 1
|
||||
# # 3 -> removed
|
||||
# # 4 -> 2
|
||||
# # !2 -> 3
|
||||
# expectok input <<EOF
|
||||
# HOA: v1
|
||||
# name: "TGBA for Fa"
|
||||
# States: 2
|
||||
# Start: 0
|
||||
# AP: 1 "a"
|
||||
# acc-name: all
|
||||
# Acceptance: 0 t
|
||||
# properties: trans-labels explicit-labels state-acc complete deterministic
|
||||
# --BODY--
|
||||
# State: 0 "F(a)"
|
||||
# [0] 1
|
||||
# [!0] 0
|
||||
# State: 1 "t"
|
||||
# [t] 1
|
||||
# --END--
|
||||
# HOA: v1
|
||||
# States: 1
|
||||
# Start: 0
|
||||
# AP: 3 "a" "b" "c"
|
||||
# acc-name: generalized-Buchi 4
|
||||
# Acceptance: 4 Inf(0)&Inf(1)&Inf(2)&Inf(3)
|
||||
# properties: trans-labels explicit-labels trans-acc complete deterministic
|
||||
# --BODY--
|
||||
# State: 0
|
||||
# [0&1&2] 0 {0 1 2}
|
||||
# [!0&1&2] 0 {1 2}
|
||||
# [0&!1&2] 0 {0 1}
|
||||
# [!0&!1&2] 0 {1}
|
||||
# [0&1&!2] 0 {0 2 3}
|
||||
# [!0&1&!2] 0 {2 3}
|
||||
# [0&!1&!2] 0 {0 3}
|
||||
# [!0&!1&!2] 0 {3}
|
||||
# --END--
|
||||
# EOF
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue