gen: hide ks_cobuchi(), introduce aut_pattern()
* spot/gen/automata.hh, spot/gen/automata.cc: Hide ks_cobuchi() behind introduce aut_pattern(), as we have already done for the formulas. * bin/genaut.cc: Simplify using this interface. * python/spot/gen.i: Introduce aut_patterns(). * tests/python/gen.ipynb, tests/python/gen.py: Adjust.
This commit is contained in:
parent
ca7f72bb4b
commit
11ca2803c9
6 changed files with 216 additions and 122 deletions
|
|
@ -43,28 +43,14 @@
|
||||||
|
|
||||||
using namespace spot;
|
using namespace spot;
|
||||||
|
|
||||||
const char argp_program_doc[] ="\
|
const char argp_program_doc[] ="Generate ω-automata from predefined patterns.";
|
||||||
Generate omega automata from predefined patterns.";
|
|
||||||
|
|
||||||
enum {
|
|
||||||
FIRST_CLASS = 256,
|
|
||||||
OPT_KS_COBUCHI = FIRST_CLASS,
|
|
||||||
LAST_CLASS,
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* const class_name[LAST_CLASS - FIRST_CLASS] =
|
|
||||||
{
|
|
||||||
"ks-cobuchi",
|
|
||||||
};
|
|
||||||
|
|
||||||
#define OPT_ALIAS(o) { #o, 0, nullptr, OPTION_ALIAS, nullptr, 0 }
|
|
||||||
|
|
||||||
static const argp_option options[] =
|
static const argp_option options[] =
|
||||||
{
|
{
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
// Keep this alphabetically sorted (expect for aliases).
|
// Keep this alphabetically sorted (expect for aliases).
|
||||||
{ nullptr, 0, nullptr, 0, "Pattern selection:", 1},
|
{ nullptr, 0, nullptr, 0, "Pattern selection:", 1},
|
||||||
{ "ks-cobuchi", OPT_KS_COBUCHI, "RANGE", 0,
|
{ "ks-cobuchi", gen::AUT_KS_COBUCHI, "RANGE", 0,
|
||||||
"A co-Büchi automaton with 2N+1 states for which any equivalent "
|
"A co-Büchi automaton with 2N+1 states for which any equivalent "
|
||||||
"deterministic co-Büchi automaton has at least 2^N/(2N+1) states.", 0},
|
"deterministic co-Büchi automaton has at least 2^N/(2N+1) states.", 0},
|
||||||
RANGE_DOC,
|
RANGE_DOC,
|
||||||
|
|
@ -75,7 +61,7 @@ static const argp_option options[] =
|
||||||
|
|
||||||
struct job
|
struct job
|
||||||
{
|
{
|
||||||
int pattern;
|
gen::aut_pattern_id pattern;
|
||||||
struct range range;
|
struct range range;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -94,7 +80,7 @@ static void
|
||||||
enqueue_job(int pattern, const char* range_str)
|
enqueue_job(int pattern, const char* range_str)
|
||||||
{
|
{
|
||||||
job j;
|
job j;
|
||||||
j.pattern = pattern;
|
j.pattern = static_cast<gen::aut_pattern_id>(pattern);
|
||||||
j.range = parse_range(range_str);
|
j.range = parse_range(range_str);
|
||||||
jobs.push_back(j);
|
jobs.push_back(j);
|
||||||
}
|
}
|
||||||
|
|
@ -102,35 +88,23 @@ enqueue_job(int pattern, const char* range_str)
|
||||||
static int
|
static int
|
||||||
parse_opt(int key, char* arg, struct argp_state*)
|
parse_opt(int key, char* arg, struct argp_state*)
|
||||||
{
|
{
|
||||||
// This switch is alphabetically-ordered.
|
if (key >= gen::AUT_BEGIN && key < gen::AUT_END)
|
||||||
switch (key)
|
|
||||||
{
|
{
|
||||||
case OPT_KS_COBUCHI:
|
|
||||||
enqueue_job(key, arg);
|
enqueue_job(key, arg);
|
||||||
break;
|
return 0;
|
||||||
default:
|
|
||||||
return ARGP_ERR_UNKNOWN;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return ARGP_ERR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
output_pattern(int pattern, int n)
|
output_pattern(gen::aut_pattern_id pattern, int n)
|
||||||
{
|
{
|
||||||
twa_graph_ptr aut = nullptr;
|
|
||||||
switch (pattern)
|
|
||||||
{
|
|
||||||
// Keep this alphabetically-ordered!
|
|
||||||
case OPT_KS_COBUCHI:
|
|
||||||
aut = spot::gen::ks_cobuchi(n);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error(100, 0, "internal error: pattern not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
process_timer timer;
|
process_timer timer;
|
||||||
|
timer.start();
|
||||||
|
twa_graph_ptr aut = spot::gen::aut_pattern(pattern, n);
|
||||||
|
timer.stop();
|
||||||
automaton_printer printer;
|
automaton_printer printer;
|
||||||
printer.print(aut, timer, nullptr, class_name[pattern - FIRST_CLASS], n);
|
printer.print(aut, timer, nullptr, aut_pattern_name(pattern), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -85,4 +85,32 @@ def ltl_patterns(*args):
|
||||||
raise RuntimeError("invalid pattern specification")
|
raise RuntimeError("invalid pattern specification")
|
||||||
for n in range(min, max + 1):
|
for n in range(min, max + 1):
|
||||||
yield ltl_pattern(pat, n)
|
yield ltl_pattern(pat, n)
|
||||||
|
|
||||||
|
def aut_patterns(*args):
|
||||||
|
"""
|
||||||
|
Generate automata patterns.
|
||||||
|
|
||||||
|
The arguments should be have one of these three forms:
|
||||||
|
- (id, n)
|
||||||
|
- (id, min, max)
|
||||||
|
- id
|
||||||
|
In the first case, the pattern id=n is generated. In the second
|
||||||
|
case, all pattern id=n for min<=n<=max are generated. The
|
||||||
|
third case is a shorthand for (id, 1, 10).
|
||||||
|
"""
|
||||||
|
for spec in args:
|
||||||
|
if type(spec) is int:
|
||||||
|
pat = spec
|
||||||
|
min = 1
|
||||||
|
max = 10
|
||||||
|
else:
|
||||||
|
ls = len(spec)
|
||||||
|
if ls == 2:
|
||||||
|
pat, min, max = spec[0], spec[1], spec[1]
|
||||||
|
elif ls == 3:
|
||||||
|
pat, min, max = spec
|
||||||
|
else:
|
||||||
|
raise RuntimeError("invalid pattern specification")
|
||||||
|
for n in range(min, max + 1):
|
||||||
|
yield aut_pattern(pat, n)
|
||||||
%}
|
%}
|
||||||
|
|
|
||||||
|
|
@ -17,75 +17,114 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <spot/twa/twagraph.hh>
|
||||||
#include <spot/gen/automata.hh>
|
#include <spot/gen/automata.hh>
|
||||||
#include <spot/twa/formula2bdd.hh>
|
|
||||||
#include <spot/tl/parse.hh>
|
#include <spot/tl/parse.hh>
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
namespace gen
|
namespace gen
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
twa_graph_ptr
|
|
||||||
ks_cobuchi(unsigned n)
|
|
||||||
{
|
{
|
||||||
if (n == 0)
|
static twa_graph_ptr
|
||||||
throw std::runtime_error("ks_cobuchi() expects a positive argument");
|
ks_cobuchi(unsigned n)
|
||||||
// the alphabet has four letters:
|
{
|
||||||
// i, s (for sigma), p (for pi), h (for hash)
|
if (n == 0)
|
||||||
// we encode this four letters alphabet thanks to two AP a and b
|
throw std::runtime_error("ks_cobuchi expects a positive argument");
|
||||||
// the exact encoding is not important
|
// the alphabet has four letters:
|
||||||
// each letter is a permutation of the set {1..2n}
|
// i, s (for sigma), p (for pi), h (for hash)
|
||||||
// s = (1 2 .. 2n) the rotation
|
// we encode this four letters alphabet thanks to two AP a and b
|
||||||
// p = (1 2) the swap of the first two elements
|
// the exact encoding is not important
|
||||||
// i is the identity
|
// each letter is a permutation of the set {1..2n}
|
||||||
// d is the identity on {2..2n} but is undefined on 1
|
// 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
|
// the automaton has 2n+1 states, numbered from 0 to 2n
|
||||||
// 0 is the initial state and the only non-deterministic state
|
// 0 is the initial state and the only non-deterministic state
|
||||||
|
|
||||||
auto dict = make_bdd_dict();
|
auto dict = make_bdd_dict();
|
||||||
auto aut = make_twa_graph(dict);
|
auto aut = make_twa_graph(dict);
|
||||||
|
|
||||||
// register aps
|
// register aps
|
||||||
aut->register_ap("a");
|
bdd a = bdd_ithvar(aut->register_ap("a"));
|
||||||
aut->register_ap("b");
|
bdd b = bdd_ithvar(aut->register_ap("b"));
|
||||||
|
|
||||||
// retrieve the four letters, and name them
|
// name the four letters
|
||||||
bdd i = formula_to_bdd(parse_formula("a&&b"), dict, aut);
|
bdd i = a & b;
|
||||||
bdd s = formula_to_bdd(parse_formula("a&&!b"), dict, aut);
|
bdd s = a & (!b);
|
||||||
bdd p = formula_to_bdd(parse_formula("!a&&b"), dict, aut);
|
bdd p = (!a) & b;
|
||||||
bdd h = formula_to_bdd(parse_formula("!a&&!b"), dict, aut);
|
bdd h = (!a) & (!b);
|
||||||
|
|
||||||
// actually build the automaton
|
// actually build the automaton
|
||||||
aut->new_states(2*n+1);
|
aut->new_states(2*n+1);
|
||||||
aut->set_init_state(0);
|
aut->set_init_state(0);
|
||||||
aut->set_acceptance(1, acc_cond::acc_code::cobuchi());
|
aut->set_acceptance(1, acc_cond::acc_code::cobuchi());
|
||||||
|
|
||||||
// from 0, we can non-deterministically jump to any state (except 0) with
|
// from 0, we can non-deterministically jump to any state
|
||||||
// any letter.
|
// (except 0) with any letter.
|
||||||
for (unsigned q = 1; q <= 2*n; ++q)
|
for (unsigned q = 1; q <= 2*n; ++q)
|
||||||
aut->new_edge(0, q, bddtrue, {0});
|
aut->new_edge(0, q, bddtrue, {0});
|
||||||
// i is the identity
|
// i is the identity
|
||||||
for (unsigned q = 1; q <= 2*n; ++q)
|
for (unsigned q = 1; q <= 2*n; ++q)
|
||||||
aut->new_edge(q, q, i);
|
aut->new_edge(q, q, i);
|
||||||
// p swaps 1 and 2, and leaves all other states invariant
|
// p swaps 1 and 2, and leaves all other states invariant
|
||||||
aut->new_edge(1, 2, p);
|
aut->new_edge(1, 2, p);
|
||||||
aut->new_edge(2, 1, p);
|
aut->new_edge(2, 1, p);
|
||||||
for (unsigned q = 3; q <= 2*n; ++q)
|
for (unsigned q = 3; q <= 2*n; ++q)
|
||||||
aut->new_edge(q, q, p);
|
aut->new_edge(q, q, p);
|
||||||
// s does to next state (mod 2*n, 0 excluded)
|
// s does to next state (mod 2*n, 0 excluded)
|
||||||
aut->new_edge(2*n, 1, s);
|
aut->new_edge(2*n, 1, s);
|
||||||
for (unsigned q = 1; q < 2*n; ++q)
|
for (unsigned q = 1; q < 2*n; ++q)
|
||||||
aut->new_edge(q, q+1, s);
|
aut->new_edge(q, q+1, s);
|
||||||
// h is the same as i, except on 1 where it goes back to the initial state
|
// h is the same as i, except on 1 where it goes back to the
|
||||||
aut->new_edge(1, 0, h);
|
// initial state
|
||||||
for (unsigned q = 2; q <= 2*n; ++q)
|
aut->new_edge(1, 0, h);
|
||||||
aut->new_edge(q, q, h);
|
for (unsigned q = 2; q <= 2*n; ++q)
|
||||||
|
aut->new_edge(q, q, h);
|
||||||
|
|
||||||
aut->merge_edges();
|
aut->merge_edges();
|
||||||
aut->prop_state_acc(true);
|
aut->prop_state_acc(true);
|
||||||
return aut;
|
return aut;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
twa_graph_ptr aut_pattern(aut_pattern_id pattern, int n)
|
||||||
|
{
|
||||||
|
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_COBUCHI:
|
||||||
|
return ks_cobuchi(n);
|
||||||
|
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-cobuchi",
|
||||||
|
};
|
||||||
|
// 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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,31 +19,48 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <spot/twa/twagraph.hh>
|
#include <spot/misc/common.hh>
|
||||||
|
#include <spot/twa/fwd.hh>
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
namespace gen
|
namespace gen
|
||||||
{
|
{
|
||||||
/// \brief A family of co-Büchi automata.
|
enum aut_pattern_id {
|
||||||
|
AUT_BEGIN = 256,
|
||||||
|
/// \brief A family of co-Büchi automata.
|
||||||
|
///
|
||||||
|
/// ks_cobuchi(n) is a co-Büchi automaton of size 2n+1 that is
|
||||||
|
/// good-for-games and that has no equivalent deterministic co-Büchi
|
||||||
|
/// automaton with less than 2^n / (2n+1) states.
|
||||||
|
/// For details and other classes, see:
|
||||||
|
///
|
||||||
|
/// @InProceedings{kuperberg2015determinisation,
|
||||||
|
/// author={Kuperberg, Denis and Skrzypczak, Micha{\l}},
|
||||||
|
/// title={On Determinisation of Good-for-Games Automata},
|
||||||
|
/// booktitle={International Colloquium on Automata, Languages, and
|
||||||
|
/// Programming},
|
||||||
|
/// pages={299--310},
|
||||||
|
/// year={2015},
|
||||||
|
/// organization={Springer}
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// Only defined for n>0
|
||||||
|
AUT_KS_COBUCHI = AUT_BEGIN,
|
||||||
|
AUT_END
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief generate an automaton from a known pattern
|
||||||
///
|
///
|
||||||
/// ks_cobuchi(n) is a co-Büchi automaton of size 2n+1 that is
|
/// The pattern is specified using one value from the aut_pattern_id
|
||||||
/// good-for-games and that has no equivalent deterministic co-Büchi
|
/// enum. See the man page of the `genaut` binary for a
|
||||||
/// automaton with less than 2^n / (2n+1) states.
|
/// description of those patterns, and bibliographic references.
|
||||||
/// For details and other classes, see:
|
SPOT_API twa_graph_ptr aut_pattern(aut_pattern_id pattern, int n);
|
||||||
|
|
||||||
|
/// \brief convert an aut_pattern_it value into a name
|
||||||
///
|
///
|
||||||
/// @InProceedings{kuperberg2015determinisation,
|
/// The returned name is suitable to be used as an option
|
||||||
/// author={Kuperberg, Denis and Skrzypczak, Micha{\l}},
|
/// key for the genaut binary.
|
||||||
/// title={On Determinisation of Good-for-Games Automata},
|
SPOT_API const char* aut_pattern_name(aut_pattern_id pattern);
|
||||||
/// booktitle={International Colloquium on Automata, Languages, and
|
|
||||||
/// Programming},
|
|
||||||
/// pages={299--310},
|
|
||||||
/// year={2015},
|
|
||||||
/// organization={Springer}
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// \pre n>0
|
|
||||||
SPOT_API twa_graph_ptr
|
|
||||||
ks_cobuchi(unsigned n);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
"language": "python",
|
"language": "python",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"prompt_number": 13
|
"prompt_number": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
|
|
@ -71,13 +71,13 @@
|
||||||
],
|
],
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "pyout",
|
"output_type": "pyout",
|
||||||
"prompt_number": 14,
|
"prompt_number": 2,
|
||||||
"text": [
|
"text": [
|
||||||
"GFp1 & GFp2 & GFp3"
|
"GFp1 & GFp2 & GFp3"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"prompt_number": 14
|
"prompt_number": 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
|
|
@ -94,13 +94,13 @@
|
||||||
],
|
],
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "pyout",
|
"output_type": "pyout",
|
||||||
"prompt_number": 15,
|
"prompt_number": 3,
|
||||||
"text": [
|
"text": [
|
||||||
"F(p & Xp & XXp & XXXp) & F(q & Xq & XXq & XXXq)"
|
"F(p & Xp & XXp & XXXp) & F(q & Xq & XXq & XXXq)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"prompt_number": 15
|
"prompt_number": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
|
|
@ -289,7 +289,7 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"prompt_number": 20
|
"prompt_number": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
|
|
@ -304,7 +304,7 @@
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"collapsed": false,
|
"collapsed": false,
|
||||||
"input": [
|
"input": [
|
||||||
"sg.ks_cobuchi(3).show('.a')"
|
"sg.aut_pattern(sg.AUT_KS_COBUCHI, 3).show('.a')"
|
||||||
],
|
],
|
||||||
"language": "python",
|
"language": "python",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
|
|
@ -312,7 +312,7 @@
|
||||||
{
|
{
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "pyout",
|
"output_type": "pyout",
|
||||||
"prompt_number": 23,
|
"prompt_number": 5,
|
||||||
"svg": [
|
"svg": [
|
||||||
"<svg height=\"295pt\" viewBox=\"0.00 0.00 734.00 295.41\" width=\"734pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
|
"<svg height=\"295pt\" viewBox=\"0.00 0.00 734.00 295.41\" width=\"734pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
|
||||||
"<g class=\"graph\" id=\"graph0\" transform=\"scale(0.906173 0.906173) rotate(0) translate(4 322)\">\n",
|
"<g class=\"graph\" id=\"graph0\" transform=\"scale(0.906173 0.906173) rotate(0) translate(4 322)\">\n",
|
||||||
|
|
@ -491,7 +491,43 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"prompt_number": 23
|
"prompt_number": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Multiple automata can be generated using the `aut_patterns()` function, which works similarly to `ltl_patterns()`."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"collapsed": false,
|
||||||
|
"input": [
|
||||||
|
"for aut in sg.aut_patterns(sg.AUT_KS_COBUCHI):\n",
|
||||||
|
" print(aut.num_states())"
|
||||||
|
],
|
||||||
|
"language": "python",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"output_type": "stream",
|
||||||
|
"stream": "stdout",
|
||||||
|
"text": [
|
||||||
|
"3\n",
|
||||||
|
"5\n",
|
||||||
|
"7\n",
|
||||||
|
"9\n",
|
||||||
|
"11\n",
|
||||||
|
"13\n",
|
||||||
|
"15\n",
|
||||||
|
"17\n",
|
||||||
|
"19\n",
|
||||||
|
"21\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prompt_number": 6
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
import spot.gen as gen
|
import spot.gen as gen
|
||||||
from sys import exit
|
from sys import exit
|
||||||
|
|
||||||
k2 = gen.ks_cobuchi(2)
|
k2 = gen.aut_pattern(gen.AUT_KS_COBUCHI, 2)
|
||||||
assert k2.prop_state_acc()
|
assert k2.prop_state_acc()
|
||||||
assert k2.num_states() == 5
|
assert k2.num_states() == 5
|
||||||
# to_str is defined in the spot package, so this makes sure
|
# to_str is defined in the spot package, so this makes sure
|
||||||
|
|
@ -32,7 +32,7 @@ assert k2.num_states() == 5
|
||||||
assert 'to_str' in dir(k2)
|
assert 'to_str' in dir(k2)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
gen.ks_cobuchi(0)
|
gen.aut_pattern(gen.AUT_KS_COBUCHI, 0)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
assert 'positive argument' in str(e)
|
assert 'positive argument' in str(e)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue