This helps working around missing C functions like strcasecmp that do not exist everywhere (e.g. on Cygwin), and for which lib/ supplies a replacement. Unfortunately we do not have such build in our current continuous integration suite, so we cannot easily detect files where such config.h inclusion would be useful. Therefore this patch simply makes it mandatory to include config.h in *.cc files. Including this in public *.hh file is currently forbidden. * spot/gen/automata.cc, spot/gen/formulas.cc, spot/kripke/fairkripke.cc, spot/kripke/kripke.cc, spot/ltsmin/ltsmin.cc, spot/misc/game.cc, spot/parseaut/fmterror.cc, spot/parsetl/fmterror.cc, spot/parsetl/parsetl.yy, spot/priv/bddalloc.cc, spot/priv/freelist.cc, spot/priv/satcommon.cc, spot/priv/trim.cc, spot/priv/weight.cc, spot/ta/ta.cc, spot/ta/taexplicit.cc, spot/ta/taproduct.cc, spot/ta/tgtaexplicit.cc, spot/ta/tgtaproduct.cc, spot/taalgos/dot.cc, spot/taalgos/emptinessta.cc, spot/taalgos/minimize.cc, spot/taalgos/reachiter.cc, spot/taalgos/statessetbuilder.cc, spot/taalgos/stats.cc, spot/taalgos/tgba2ta.cc, spot/tl/apcollect.cc, spot/tl/contain.cc, spot/tl/declenv.cc, spot/tl/defaultenv.cc, spot/tl/dot.cc, spot/tl/exclusive.cc, spot/tl/hierarchy.cc, spot/tl/length.cc, spot/tl/ltlf.cc, spot/tl/mark.cc, spot/tl/mutation.cc, spot/tl/nenoform.cc, spot/tl/print.cc, spot/tl/randomltl.cc, spot/tl/relabel.cc, spot/tl/remove_x.cc, spot/tl/simplify.cc, spot/tl/snf.cc, spot/tl/unabbrev.cc, spot/twa/acc.cc, spot/twa/bdddict.cc, spot/twa/bddprint.cc, spot/twa/formula2bdd.cc, spot/twa/taatgba.cc, spot/twa/twa.cc, spot/twa/twagraph.cc, spot/twa/twaproduct.cc, spot/twaalgos/aiger.cc, spot/twaalgos/alternation.cc, spot/twaalgos/are_isomorphic.cc, spot/twaalgos/bfssteps.cc, spot/twaalgos/canonicalize.cc, spot/twaalgos/cleanacc.cc, spot/twaalgos/cobuchi.cc, spot/twaalgos/complement.cc, spot/twaalgos/complete.cc, spot/twaalgos/compsusp.cc, spot/twaalgos/couvreurnew.cc, spot/twaalgos/cycles.cc, spot/twaalgos/degen.cc, spot/twaalgos/determinize.cc, spot/twaalgos/dot.cc, spot/twaalgos/dtbasat.cc, spot/twaalgos/dtwasat.cc, spot/twaalgos/dualize.cc, spot/twaalgos/emptiness.cc, spot/twaalgos/gtec/ce.cc, spot/twaalgos/gtec/gtec.cc, spot/twaalgos/gtec/sccstack.cc, spot/twaalgos/gtec/status.cc, spot/twaalgos/gv04.cc, spot/twaalgos/hoa.cc, spot/twaalgos/iscolored.cc, spot/twaalgos/isdet.cc, spot/twaalgos/isunamb.cc, spot/twaalgos/isweakscc.cc, spot/twaalgos/langmap.cc, spot/twaalgos/lbtt.cc, spot/twaalgos/ltl2taa.cc, spot/twaalgos/ltl2tgba_fm.cc, spot/twaalgos/magic.cc, spot/twaalgos/mask.cc, spot/twaalgos/minimize.cc, spot/twaalgos/neverclaim.cc, spot/twaalgos/parity.cc, spot/twaalgos/postproc.cc, spot/twaalgos/powerset.cc, spot/twaalgos/product.cc, spot/twaalgos/rabin2parity.cc, spot/twaalgos/randomgraph.cc, spot/twaalgos/randomize.cc, spot/twaalgos/reachiter.cc, spot/twaalgos/relabel.cc, spot/twaalgos/remfin.cc, spot/twaalgos/remprop.cc, spot/twaalgos/sbacc.cc, spot/twaalgos/sccfilter.cc, spot/twaalgos/sccinfo.cc, spot/twaalgos/se05.cc, spot/twaalgos/sepsets.cc, spot/twaalgos/simulation.cc, spot/twaalgos/split.cc, spot/twaalgos/stats.cc, spot/twaalgos/strength.cc, spot/twaalgos/stripacc.cc, spot/twaalgos/stutter.cc, spot/twaalgos/sum.cc, spot/twaalgos/tau03.cc, spot/twaalgos/tau03opt.cc, spot/twaalgos/totgba.cc, spot/twaalgos/toweak.cc, spot/twaalgos/translate.cc, spot/twaalgos/word.cc, tests/core/acc.cc, tests/core/bitvect.cc, tests/core/checkpsl.cc, tests/core/checkta.cc, tests/core/consterm.cc, tests/core/emptchk.cc, tests/core/equalsf.cc, tests/core/graph.cc, tests/core/ikwiad.cc, tests/core/intvcmp2.cc, tests/core/intvcomp.cc, tests/core/kind.cc, tests/core/kripkecat.cc, tests/core/length.cc, tests/core/ltlrel.cc, tests/core/ngraph.cc, tests/core/parity.cc, tests/core/randtgba.cc, tests/core/readltl.cc, tests/core/reduc.cc, tests/core/safra.cc, tests/core/sccif.cc, tests/core/syntimpl.cc, tests/core/taatgba.cc, tests/core/tostring.cc, tests/core/trival.cc, tests/core/twagraph.cc, tests/ltsmin/modelcheck.cc, spot/parseaut/scanaut.ll, spot/parsetl/scantl.ll: Include config.h. * spot/gen/Makefile.am, spot/graph/Makefile.am, spot/kripke/Makefile.am, spot/ltsmin/Makefile.am, spot/parseaut/Makefile.am, spot/parsetl/Makefile.am, spot/priv/Makefile.am, spot/ta/Makefile.am, spot/taalgos/Makefile.am, spot/tl/Makefile.am, spot/twa/Makefile.am, spot/twaalgos/Makefile.am, spot/twaalgos/gtec/Makefile.am, tests/Makefile.am: Add the -I lib/ flags. * tests/sanity/includes.test: Catch missing config.h in *.cc, and diagnose config.h in *.hh. * tests/sanity/style.test: Better diagnostics.
218 lines
6.9 KiB
C++
218 lines
6.9 KiB
C++
// -*- coding: utf-8 -*-
|
|
// Copyright (C) 2017-2018 Laboratoire de Recherche et Developpement
|
|
// 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 "config.h"
|
|
#include <spot/twa/twagraph.hh>
|
|
#include <spot/gen/automata.hh>
|
|
#include <spot/tl/parse.hh>
|
|
|
|
namespace spot
|
|
{
|
|
namespace gen
|
|
{
|
|
namespace
|
|
{
|
|
static twa_graph_ptr
|
|
ks_nca(unsigned n, bdd_dict_ptr dict)
|
|
{
|
|
if (n == 0)
|
|
throw std::runtime_error("ks_nca expects a positive argument");
|
|
// the alphabet has four letters:
|
|
// i, s (for sigma), p (for pi), h (for hash)
|
|
// we encode this four letters alphabet thanks to two AP a and b
|
|
// the exact encoding is not important
|
|
// each letter is a permutation of the set {1..2n}
|
|
// s = (1 2 .. 2n) the rotation
|
|
// p = (1 2) the swap of the first two elements
|
|
// i is the identity
|
|
// d is the identity on {2..2n} but is undefined on 1
|
|
|
|
// the automaton has 2n+1 states, numbered from 0 to 2n
|
|
// 0 is the initial state and the only non-deterministic state
|
|
|
|
auto aut = make_twa_graph(dict);
|
|
|
|
// register aps
|
|
bdd a = bdd_ithvar(aut->register_ap("a"));
|
|
bdd b = bdd_ithvar(aut->register_ap("b"));
|
|
|
|
// name the four letters
|
|
bdd i = a & b;
|
|
bdd s = a & (!b);
|
|
bdd p = (!a) & b;
|
|
bdd h = (!a) & (!b);
|
|
|
|
// actually build the automaton
|
|
aut->new_states(2*n+1);
|
|
aut->set_init_state(0);
|
|
aut->set_acceptance(1, acc_cond::acc_code::cobuchi());
|
|
|
|
// from 0, we can non-deterministically jump to any state
|
|
// (except 0) with any letter.
|
|
for (unsigned q = 1; q <= 2*n; ++q)
|
|
aut->new_edge(0, q, bddtrue, {0});
|
|
// i is the identity
|
|
for (unsigned q = 1; q <= 2*n; ++q)
|
|
aut->new_edge(q, q, i);
|
|
// p swaps 1 and 2, and leaves all other states invariant
|
|
aut->new_edge(1, 2, p);
|
|
aut->new_edge(2, 1, p);
|
|
for (unsigned q = 3; q <= 2*n; ++q)
|
|
aut->new_edge(q, q, p);
|
|
// s goes to next state (mod 2*n, 0 excluded)
|
|
aut->new_edge(2*n, 1, s);
|
|
for (unsigned q = 1; q < 2*n; ++q)
|
|
aut->new_edge(q, q+1, s);
|
|
// h is the same as i, except on 1 where it goes back to the
|
|
// initial state
|
|
aut->new_edge(1, 0, h);
|
|
for (unsigned q = 2; q <= 2*n; ++q)
|
|
aut->new_edge(q, q, h);
|
|
|
|
aut->merge_edges();
|
|
aut->prop_state_acc(true);
|
|
aut->prop_universal(false);
|
|
aut->prop_complete(true);
|
|
aut->prop_inherently_weak(false);
|
|
aut->prop_stutter_invariant(false);
|
|
aut->prop_semi_deterministic(false);
|
|
return aut;
|
|
}
|
|
|
|
static twa_graph_ptr
|
|
l_nba(unsigned n, bdd_dict_ptr dict)
|
|
{
|
|
if (n == 0)
|
|
throw std::runtime_error("l_nba expects a positive argument");
|
|
|
|
auto aut = make_twa_graph(dict);
|
|
|
|
bdd p1 = bdd_ithvar(aut->register_ap("a"));
|
|
bdd p2 = bdd_ithvar(aut->register_ap("b"));
|
|
bdd a = p1 - p2;
|
|
bdd b = p2 - p1;
|
|
bdd s = p1 & p2;
|
|
bdd all = p1 | p2;
|
|
|
|
aut->new_states(3 * n + 1);
|
|
aut->set_init_state(1);
|
|
aut->set_buchi();
|
|
|
|
aut->new_acc_edge(0, n + 1, a);
|
|
aut->new_edge(2 * n + 1, 0, b);
|
|
for (unsigned s = 1; s <= n; ++s)
|
|
{
|
|
aut->new_edge(s + n, std::min(s + n + 1, 2 * n), a);
|
|
aut->new_edge(s + n, s, b);
|
|
aut->new_edge(s, s, all);
|
|
aut->new_edge(s, s + 2 * n, a);
|
|
aut->new_edge(std::min(s + 2 * n + 1, 3 * n), s + 2 * n, a);
|
|
}
|
|
|
|
aut->prop_state_acc(true);
|
|
aut->prop_universal(false);
|
|
aut->prop_complete(false);
|
|
aut->prop_inherently_weak(false);
|
|
aut->prop_stutter_invariant(false);
|
|
aut->prop_semi_deterministic(false);
|
|
return aut;
|
|
}
|
|
|
|
static twa_graph_ptr
|
|
l_dsa(unsigned n, bdd_dict_ptr dict)
|
|
{
|
|
if (n < 1 || n > 16)
|
|
throw std::runtime_error("l_dsa expects 1 <= n <= 16");
|
|
|
|
auto aut = make_twa_graph(dict);
|
|
|
|
bdd a = bdd_ithvar(aut->register_ap("a"));
|
|
bdd b = !a;
|
|
|
|
aut->set_acceptance(2 * n, acc_cond::acc_code::streett(n));
|
|
aut->new_states(4 * n);
|
|
aut->set_init_state(0);
|
|
|
|
for (unsigned s = 0; s < n; ++s)
|
|
{
|
|
unsigned col1 = 4 * s;
|
|
unsigned col2 = 4 * s + 1;
|
|
unsigned col3 = 4 * s + 2;
|
|
unsigned col4 = 4 * s + 3;
|
|
aut->new_edge(col1, 2, a, {2 * s});
|
|
aut->new_edge(col2, col1, b);
|
|
aut->new_edge(col2, std::min(col2 + 4, 4 * n - 3), a);
|
|
aut->new_edge(col3, col4, b);
|
|
aut->new_edge(col3, std::min(col3 + 4, 4 * n - 2), a);
|
|
aut->new_edge(col4, 1, a, {2 * s + 1});
|
|
}
|
|
|
|
aut->prop_state_acc(true);
|
|
aut->prop_universal(true);
|
|
aut->prop_complete(false);
|
|
aut->prop_inherently_weak(false);
|
|
aut->prop_stutter_invariant(false);
|
|
aut->prop_semi_deterministic(true);
|
|
return aut;
|
|
}
|
|
}
|
|
|
|
twa_graph_ptr aut_pattern(aut_pattern_id pattern, int n, bdd_dict_ptr dict)
|
|
{
|
|
if (n < 0)
|
|
{
|
|
std::ostringstream err;
|
|
err << "pattern argument for " << aut_pattern_name(pattern)
|
|
<< " should be positive";
|
|
throw std::runtime_error(err.str());
|
|
}
|
|
|
|
switch (pattern)
|
|
{
|
|
// Keep this alphabetically-ordered!
|
|
case AUT_KS_NCA:
|
|
return ks_nca(n, dict);
|
|
case AUT_L_NBA:
|
|
return l_nba(n, dict);
|
|
case AUT_L_DSA:
|
|
return l_dsa(n, dict);
|
|
case AUT_END:
|
|
break;
|
|
}
|
|
throw std::runtime_error("unsupported pattern");
|
|
}
|
|
|
|
const char* aut_pattern_name(aut_pattern_id pattern)
|
|
{
|
|
static const char* const class_name[] =
|
|
{
|
|
"ks-nca",
|
|
"l-nba",
|
|
"l-dsa",
|
|
};
|
|
// Make sure we do not forget to update the above table every
|
|
// time a new pattern is added.
|
|
static_assert(sizeof(class_name)/sizeof(*class_name)
|
|
== AUT_END - AUT_BEGIN, "size mismatch");
|
|
if (pattern < AUT_BEGIN || pattern >= AUT_END)
|
|
throw std::runtime_error("unsupported pattern");
|
|
return class_name[pattern - AUT_BEGIN];
|
|
}
|
|
}
|
|
}
|