forq: make it easier to select contains's version
* spot/twaalgos/contains.hh, spot/twaalgos/contains.cc (containment_select_version): New function. (contains): Use it. * spot/twa/twa.cc (exclusive_word): Likewise. * bin/autfilt.cc (--included-in): Adjust to use forq depending on containement_select_version. * bin/man/spot-x.x: Adjust documentation of CONTAINMENT_SELECT_VERSION. * tests/core/included.test, tests/python/forq_contains.py: Add more tests. * NEWS: Mention the new feature.
This commit is contained in:
parent
ca4e6c4b48
commit
05d7622f8f
8 changed files with 178 additions and 83 deletions
13
NEWS
13
NEWS
|
|
@ -65,6 +65,19 @@ New in spot 2.11.6.dev (not yet released)
|
||||||
36 seconds; it now produce an AIG circuit with 53 nodes in only
|
36 seconds; it now produce an AIG circuit with 53 nodes in only
|
||||||
0.1 second.
|
0.1 second.
|
||||||
|
|
||||||
|
- spot::contains_forq() is a implementation of the paper "FORQ-Based
|
||||||
|
Language Inclusion Formal Testing" (Doveri, Ganty, Mazzocchi;
|
||||||
|
CAV'22) contributed by Jonah Romero.
|
||||||
|
|
||||||
|
- spot::contains() still default to the complementation-based
|
||||||
|
algorithm, however by calling
|
||||||
|
spot::containment_select_version("forq") or by setting
|
||||||
|
SPOT_CONTAINMENT_CHECK=forq in the environment, the
|
||||||
|
spot::contains_forq() implementation will be used instead when
|
||||||
|
applicable (inclusion between Büchi automata).
|
||||||
|
|
||||||
|
The above also impacts autfilt --included-in option.
|
||||||
|
|
||||||
Bugs fixed:
|
Bugs fixed:
|
||||||
|
|
||||||
- tgba_determinize()'s use_simulation option would cause it to
|
- tgba_determinize()'s use_simulation option would cause it to
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
#include <spot/misc/timer.hh>
|
#include <spot/misc/timer.hh>
|
||||||
#include <spot/parseaut/public.hh>
|
#include <spot/parseaut/public.hh>
|
||||||
#include <spot/tl/exclusive.hh>
|
#include <spot/tl/exclusive.hh>
|
||||||
|
#include <spot/twaalgos/alternation.hh>
|
||||||
#include <spot/twaalgos/are_isomorphic.hh>
|
#include <spot/twaalgos/are_isomorphic.hh>
|
||||||
#include <spot/twaalgos/canonicalize.hh>
|
#include <spot/twaalgos/canonicalize.hh>
|
||||||
#include <spot/twaalgos/cobuchi.hh>
|
#include <spot/twaalgos/cobuchi.hh>
|
||||||
|
|
@ -984,12 +985,24 @@ parse_opt(int key, char* arg, struct argp_state*)
|
||||||
break;
|
break;
|
||||||
case OPT_INCLUDED_IN:
|
case OPT_INCLUDED_IN:
|
||||||
{
|
{
|
||||||
auto aut = ensure_deterministic(read_automaton(arg, opt->dict), true);
|
auto aut = read_automaton(arg, opt->dict);
|
||||||
aut = spot::dualize(aut);
|
if (spot::containment_select_version() == 0)
|
||||||
if (!opt->included_in)
|
{
|
||||||
opt->included_in = aut;
|
aut = spot::complement(aut);
|
||||||
|
if (!aut->is_existential())
|
||||||
|
aut = spot::remove_alternation(aut);
|
||||||
|
if (!opt->included_in)
|
||||||
|
opt->included_in = aut;
|
||||||
|
else
|
||||||
|
opt->included_in = ::product_or(opt->included_in, aut);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
opt->included_in = ::product_or(opt->included_in, aut);
|
{
|
||||||
|
if (opt->included_in)
|
||||||
|
error(2, 0, "FORQ-based inclusion check only works "
|
||||||
|
"with one inclusion-test at a time");
|
||||||
|
opt->included_in = aut;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPT_INHERENTLY_WEAK_SCCS:
|
case OPT_INHERENTLY_WEAK_SCCS:
|
||||||
|
|
@ -1519,7 +1532,12 @@ namespace
|
||||||
if (opt->intersect)
|
if (opt->intersect)
|
||||||
matched &= aut->intersects(opt->intersect);
|
matched &= aut->intersects(opt->intersect);
|
||||||
if (opt->included_in)
|
if (opt->included_in)
|
||||||
matched &= !aut->intersects(opt->included_in);
|
{
|
||||||
|
if (spot::containment_select_version() == 0)
|
||||||
|
matched &= !aut->intersects(opt->included_in);
|
||||||
|
else
|
||||||
|
matched &= spot::contains(opt->included_in, aut);
|
||||||
|
}
|
||||||
if (opt->equivalent_pos)
|
if (opt->equivalent_pos)
|
||||||
matched &= !aut->intersects(opt->equivalent_neg)
|
matched &= !aut->intersects(opt->equivalent_neg)
|
||||||
&& spot::contains(aut, opt->equivalent_pos);
|
&& spot::contains(aut, opt->equivalent_pos);
|
||||||
|
|
|
||||||
|
|
@ -51,12 +51,13 @@ If this variable is set to any value, statistics about BDD garbage
|
||||||
collection and resizing will be output on standard error.
|
collection and resizing will be output on standard error.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fSPOT_CONTAINMENT_CHECK\fR
|
\fBSPOT_CONTAINMENT_CHECK\fR
|
||||||
Specifies which inclusion algorithm spot should use. This can currently
|
Specifies which inclusion algorithm Spot should use. If the variable
|
||||||
take on 1 of 2 values: 0 for the legacy implementation, and 1 for the
|
is unset, or set to \fB"default"\fR, containment checks are done
|
||||||
forq implementation [6] (See bibliography below). Forq uses buchi
|
using a complementation-based procedure. If the variable is set to
|
||||||
automata in order to determine inclusion, and will default to the legacy
|
\fB"forq"\fR, and FORQ-based containment check is used for Büchi automata
|
||||||
version if these constraints are not satisfied.
|
(the default procedure is still used for non-Büchi automata). See
|
||||||
|
[6] in the bibliography below.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fBSPOT_DEFAULT_FORMAT\fR
|
\fBSPOT_DEFAULT_FORMAT\fR
|
||||||
|
|
@ -335,24 +336,12 @@ disabled with \fB-x gf-guarantee=0\fR.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
6.
|
6.
|
||||||
Doveri, Kyveli and Ganty, Pierre and Mazzocchi, Nicolas:
|
Kyveli Doveri and Pierre Ganty and Nicolas Mazzocchi:
|
||||||
FORQ-Based Language Inclusion Formal Testing.
|
FORQ-Based Language Inclusion Formal Testing.
|
||||||
Proceedings of CAV'22. LNCS 13372.
|
Proceedings of CAV'22. LNCS 13372.
|
||||||
|
|
||||||
We propose a novel algorithm to decide the language inclusion between
|
The containment check implemented as spot::contains_forq(), and
|
||||||
(nondeterministic) Büchi automata, a PSpace-complete problem. Our approach,
|
used for Büchi automata when \fBSPOT_CONTAINMENT_CHECK=forq\fR.
|
||||||
like others before, leverage a notion of quasiorder to prune the search for a
|
|
||||||
counterexample by discarding candidates which are subsumed by others for the
|
|
||||||
quasiorder.Discarded candidates are guaranteed to not compromise the
|
|
||||||
completeness of the algorithm. The novelty of our work lies in the quasiorder k
|
|
||||||
used to discard candidates. We introduce FORQs (family of right quasiorders)
|
|
||||||
that we obtain by adapting the notion of family of right congruences put forward
|
|
||||||
by Maler and Staiger in 1993. We define a FORQ-based inclusion algorithm which
|
|
||||||
we prove correct and instantiate it for a specific FORQ, called the structural
|
|
||||||
FORQ, induced by the B\"uchi automaton to the right of the inclusion sign. The
|
|
||||||
resulting implementation, called Forklift, scales up better than the
|
|
||||||
state-of-the-art on a variety of benchmarks including benchmarks from program
|
|
||||||
verification and theorem proving for word combinatorics.
|
|
||||||
|
|
||||||
[SEE ALSO]
|
[SEE ALSO]
|
||||||
.BR ltl2tgba (1)
|
.BR ltl2tgba (1)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include <spot/twaalgos/alternation.hh>
|
#include <spot/twaalgos/alternation.hh>
|
||||||
#include <spot/twa/twaproduct.hh>
|
#include <spot/twa/twaproduct.hh>
|
||||||
#include <spot/twaalgos/forq_contains.hh>
|
#include <spot/twaalgos/forq_contains.hh>
|
||||||
|
#include <spot/twaalgos/contains.hh>
|
||||||
#include <spot/twaalgos/complement.hh>
|
#include <spot/twaalgos/complement.hh>
|
||||||
#include <spot/twaalgos/isdet.hh>
|
#include <spot/twaalgos/isdet.hh>
|
||||||
#include <spot/twaalgos/product.hh>
|
#include <spot/twaalgos/product.hh>
|
||||||
|
|
@ -213,6 +214,7 @@ namespace spot
|
||||||
return make_twa_graph(aut_in, twa::prop_set::all());
|
return make_twa_graph(aut_in, twa::prop_set::all());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
twa_run_ptr
|
twa_run_ptr
|
||||||
twa::exclusive_run(const_twa_ptr other) const
|
twa::exclusive_run(const_twa_ptr other) const
|
||||||
{
|
{
|
||||||
|
|
@ -235,37 +237,21 @@ namespace spot
|
||||||
const_twa_ptr a = shared_from_this();
|
const_twa_ptr a = shared_from_this();
|
||||||
const_twa_ptr b = other;
|
const_twa_ptr b = other;
|
||||||
|
|
||||||
enum class containment_type : unsigned { LEGACY = 0, FORQ };
|
|
||||||
static containment_type containment = [&]()
|
|
||||||
{
|
|
||||||
char* s = getenv("SPOT_EXCLUSIVE_WORD");
|
|
||||||
// We expect a single digit that represents a valid enumeration value
|
|
||||||
if (!s)
|
|
||||||
return containment_type::LEGACY;
|
|
||||||
else if (*s == '\0' || *(s + 1) != '\0' || *s < '0' || *s > '1')
|
|
||||||
throw std::runtime_error("Invalid value for enviroment variable: "
|
|
||||||
"SPOT_EXCLUSIVE_WORD");
|
|
||||||
else
|
|
||||||
return static_cast<containment_type>(*s - '0');
|
|
||||||
}();
|
|
||||||
|
|
||||||
// We have to find a word in A\B or in B\A. When possible, let's
|
// We have to find a word in A\B or in B\A. When possible, let's
|
||||||
// make sure the first automaton we complement, i.e., b, is deterministic.
|
// make sure the first automaton we complement, i.e., b, is deterministic.
|
||||||
auto a_twa_as_graph = std::dynamic_pointer_cast<const twa_graph>(a);
|
if (auto a_twa_as_graph = std::dynamic_pointer_cast<const twa_graph>(a))
|
||||||
auto b_twa_as_graph = std::dynamic_pointer_cast<const twa_graph>(b);
|
|
||||||
if (a_twa_as_graph)
|
|
||||||
if (is_deterministic(a_twa_as_graph))
|
if (is_deterministic(a_twa_as_graph))
|
||||||
std::swap(a, b);
|
std::swap(a, b);
|
||||||
|
|
||||||
if (containment == containment_type::FORQ
|
if (containment_select_version() == 1
|
||||||
&& a_twa_as_graph
|
&& a->acc().is_buchi()
|
||||||
&& b_twa_as_graph
|
&& b->acc().is_buchi())
|
||||||
&& a_twa_as_graph->acc().is_buchi()
|
|
||||||
&& b_twa_as_graph->acc().is_buchi())
|
|
||||||
{
|
{
|
||||||
if (auto word = difference_word_forq(a_twa_as_graph, b_twa_as_graph))
|
auto ag = ensure_graph(a);
|
||||||
|
auto bg = ensure_graph(b);
|
||||||
|
if (auto word = difference_word_forq(ag, bg))
|
||||||
return word;
|
return word;
|
||||||
return difference_word_forq(b_twa_as_graph, a_twa_as_graph);
|
return difference_word_forq(bg, ag);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// -*- coding: utf-8 -*-
|
// -*- coding: utf-8 -*-
|
||||||
// Copyright (C) 2018, 2019, 2022 Laboratoire de Recherche et Développement de
|
// Copyright (C) 2018, 2019, 2022, 2023 Laboratoire de Recherche et
|
||||||
// l'Epita.
|
// Développement de l'Epita.
|
||||||
//
|
//
|
||||||
// This file is part of Spot, a model checking library.
|
// This file is part of Spot, a model checking library.
|
||||||
//
|
//
|
||||||
|
|
@ -33,39 +33,25 @@ namespace spot
|
||||||
{
|
{
|
||||||
return ltl_to_tgba_fm(f, dict);
|
return ltl_to_tgba_fm(f, dict);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_buchi_automata(const_twa_graph_ptr const& aut)
|
static const_twa_graph_ptr
|
||||||
{
|
ensure_graph(const const_twa_ptr& aut_in)
|
||||||
return spot::acc_cond::acc_code::buchi() == aut->get_acceptance();
|
{
|
||||||
|
const_twa_graph_ptr aut =
|
||||||
|
std::dynamic_pointer_cast<const twa_graph>(aut_in);
|
||||||
|
if (aut)
|
||||||
|
return aut;
|
||||||
|
return make_twa_graph(aut_in, twa::prop_set::all());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contains(const_twa_graph_ptr left, const_twa_ptr right)
|
bool contains(const_twa_graph_ptr left, const_twa_ptr right)
|
||||||
{
|
{
|
||||||
enum class containment_type : unsigned { LEGACY = 0, FORQ };
|
if (containment_select_version() == 1
|
||||||
static containment_type containment = [&]()
|
&& left->acc().is_buchi() && right->acc().is_buchi())
|
||||||
{
|
return contains_forq(left, ensure_graph(right));
|
||||||
char* s = getenv("SPOT_CONTAINMENT_CHECK");
|
|
||||||
// We expect a single digit that represents a valid enumeration value
|
|
||||||
if (!s)
|
|
||||||
return containment_type::LEGACY;
|
|
||||||
else if (*s == '\0' || *(s + 1) != '\0' || *s < '0' || *s > '1')
|
|
||||||
throw std::runtime_error("Invalid value for enviroment variable: "
|
|
||||||
"SPOT_CONTAINMENT_CHECK");
|
|
||||||
else
|
|
||||||
return static_cast<containment_type>(*s - '0');
|
|
||||||
}();
|
|
||||||
|
|
||||||
auto as_graph = std::dynamic_pointer_cast<const twa_graph>(right);
|
|
||||||
bool uses_buchi = is_buchi_automata(left) && is_buchi_automata(as_graph);
|
|
||||||
if (containment == containment_type::FORQ && uses_buchi && as_graph)
|
|
||||||
{
|
|
||||||
return contains_forq(left, as_graph);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
return !complement(left)->intersects(right);
|
||||||
return !complement(left)->intersects(right);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contains(const_twa_graph_ptr left, formula right)
|
bool contains(const_twa_graph_ptr left, formula right)
|
||||||
|
|
@ -111,4 +97,32 @@ namespace spot
|
||||||
{
|
{
|
||||||
return contains(right, left) && contains(left, right);
|
return contains(right, left) && contains(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int containment_select_version(const char* version)
|
||||||
|
{
|
||||||
|
static int pref = -1;
|
||||||
|
const char *env = nullptr;
|
||||||
|
if (!version && pref < 0)
|
||||||
|
version = env = getenv("SPOT_CONTAINMENT_CHECK");
|
||||||
|
if (version)
|
||||||
|
{
|
||||||
|
if (!strcasecmp(version, "default"))
|
||||||
|
pref = 0;
|
||||||
|
else if (!strcasecmp(version, "forq"))
|
||||||
|
pref = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char* err = ("containment_select_version(): argument"
|
||||||
|
" should be one of {default,forq}");
|
||||||
|
if (env)
|
||||||
|
err = "SPOT_CONTAINMENT_CHECK should be one of {default,forq}";
|
||||||
|
throw std::runtime_error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pref < 0)
|
||||||
|
{
|
||||||
|
pref = 0;
|
||||||
|
}
|
||||||
|
return pref;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// -*- coding: utf-8 -*-
|
// -*- coding: utf-8 -*-
|
||||||
// Copyright (C) 2018, 2022 Laboratoire de Recherche et Développement de
|
// Copyright (C) 2018, 2022, 2023 Laboratoire de Recherche et
|
||||||
// l'Epita.
|
// Développement de l'Epita.
|
||||||
//
|
//
|
||||||
// This file is part of Spot, a model checking library.
|
// This file is part of Spot, a model checking library.
|
||||||
//
|
//
|
||||||
|
|
@ -62,4 +62,30 @@ namespace spot
|
||||||
SPOT_API bool are_equivalent(formula left, const_twa_graph_ptr right);
|
SPOT_API bool are_equivalent(formula left, const_twa_graph_ptr right);
|
||||||
SPOT_API bool are_equivalent(formula left, formula right);
|
SPOT_API bool are_equivalent(formula left, formula right);
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
/// \ingroup containment
|
||||||
|
///
|
||||||
|
/// Query, or change the version of the containment check to use by
|
||||||
|
/// contains() or twa::exclusive_run().
|
||||||
|
///
|
||||||
|
/// By default those containment checks use a complementation-based
|
||||||
|
/// algorithm that is generic that work on any acceptance condition.
|
||||||
|
/// Alternative algorithms such as contains_forq() are available,
|
||||||
|
/// for Büchi automata, but are not used by default.
|
||||||
|
///
|
||||||
|
/// When calling this function \a version can be:
|
||||||
|
/// - "default" to force the above default containment checks to be used
|
||||||
|
/// - "forq" to use contains_forq() when possible
|
||||||
|
/// - nullptr do not modify the preference.
|
||||||
|
///
|
||||||
|
/// If the first call to containement_select_version() is done with
|
||||||
|
/// nullptr as an argument, then the value of the
|
||||||
|
/// SPOT_CONTAINMENT_CHECK environment variable is used instead.
|
||||||
|
///
|
||||||
|
/// In all cases, the preferred containment check is returned as an
|
||||||
|
/// integer. This integer is meant to be used by Spot's algorithms
|
||||||
|
/// to select the desired containment check to apply, but it's
|
||||||
|
/// encoding (currently 1 for FORQ, 0 for default) should be
|
||||||
|
/// regarded as an implementation detail subject to change.
|
||||||
|
SPOT_API int containment_select_version(const char* version = nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2016, 2022 Laboratoire de Recherche et Développement
|
# Copyright (C) 2016, 2022, 2023 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.
|
||||||
|
|
@ -38,6 +38,20 @@ run 0 autfilt -q gab.hoa --included-in fga.hoa --included-in fgb.hoa
|
||||||
run 1 autfilt -q ga.hoa --included-in fga.hoa --included-in fgb.hoa
|
run 1 autfilt -q ga.hoa --included-in fga.hoa --included-in fgb.hoa
|
||||||
run 0 autfilt -q false.hoa --included-in fga.hoa
|
run 0 autfilt -q false.hoa --included-in fga.hoa
|
||||||
|
|
||||||
|
SPOT_CONTAINMENT_CHECK=forq run 0 autfilt -q fga.hoa --included-in gfa.hoa
|
||||||
|
SPOT_CONTAINMENT_CHECK=forq run 0 autfilt -q fga.hoa --included-in fga.hoa
|
||||||
|
SPOT_CONTAINMENT_CHECK=forq run 1 autfilt -q gfa.hoa --included-in fga.hoa
|
||||||
|
SPOT_CONTAINMENT_CHECK=forq \
|
||||||
|
run 2 autfilt -q gab.hoa --included-in fga.hoa --included-in fgb.hoa
|
||||||
|
SPOT_CONTAINMENT_CHECK=forq \
|
||||||
|
run 2 autfilt -q ga.hoa --included-in fga.hoa --included-in fgb.hoa
|
||||||
|
SPOT_CONTAINMENT_CHECK=forq run 0 autfilt -q false.hoa --included-in fga.hoa
|
||||||
|
|
||||||
|
SPOT_CONTAINMENT_CHECK=error \
|
||||||
|
autfilt -q fga.hoa --included-in gfa.hoa >err && exit 1
|
||||||
|
test $? -eq 2
|
||||||
|
grep 'SPOT_CONTAINMENT_CHECK.*forq' error
|
||||||
|
|
||||||
run 1 autfilt -q gfa.hoa --equivalent-to fga.hoa
|
run 1 autfilt -q gfa.hoa --equivalent-to fga.hoa
|
||||||
run 1 autfilt -q fga.hoa --equivalent-to gfa.hoa
|
run 1 autfilt -q fga.hoa --equivalent-to gfa.hoa
|
||||||
|
|
||||||
|
|
@ -61,6 +75,7 @@ ltl2tgba '!(a U c)' | autfilt --product-or a1.hoa > out.hoa
|
||||||
ltl2tgba true | autfilt out.hoa --equivalent-to - && exit 1
|
ltl2tgba true | autfilt out.hoa --equivalent-to - && exit 1
|
||||||
|
|
||||||
# In Spot 2.10, the following was very slow.
|
# In Spot 2.10, the following was very slow.
|
||||||
|
export SPOT_CONTAINMENT_CHECK=default
|
||||||
for n in 1 2 4 8 16 512 1024 2048 4096 8192; do
|
for n in 1 2 4 8 16 512 1024 2048 4096 8192; do
|
||||||
genaut --cyclist-trace-nba=$n > trace.hoa
|
genaut --cyclist-trace-nba=$n > trace.hoa
|
||||||
genaut --cyclist-proof-dba=$n > proof.hoa
|
genaut --cyclist-proof-dba=$n > proof.hoa
|
||||||
|
|
@ -68,4 +83,13 @@ for n in 1 2 4 8 16 512 1024 2048 4096 8192; do
|
||||||
autfilt -q --included-in=proof.hoa trace.hoa && exit 1
|
autfilt -q --included-in=proof.hoa trace.hoa && exit 1
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# The forq-based version does not scale well on this particular test
|
||||||
|
export SPOT_CONTAINMENT_CHECK=forq
|
||||||
|
for n in 1 2 4 8 16 128; do
|
||||||
|
genaut --cyclist-trace-nba=$n > trace.hoa
|
||||||
|
genaut --cyclist-proof-dba=$n > proof.hoa
|
||||||
|
autfilt -q --included-in=trace.hoa proof.hoa || exit 1
|
||||||
|
autfilt -q --included-in=proof.hoa trace.hoa && exit 1
|
||||||
|
done
|
||||||
|
|
||||||
:
|
:
|
||||||
|
|
|
||||||
|
|
@ -324,3 +324,28 @@ State: 11 {0}
|
||||||
--END--""")
|
--END--""")
|
||||||
|
|
||||||
do_symmetric_test(subset, superset)
|
do_symmetric_test(subset, superset)
|
||||||
|
|
||||||
|
|
||||||
|
tba = spot.translate('GFa')
|
||||||
|
tgba = spot.translate('GFa & GFb')
|
||||||
|
tc.assertTrue(spot.contains(tba, tgba))
|
||||||
|
try:
|
||||||
|
spot.containment_select_version("fork")
|
||||||
|
except RuntimeError as e:
|
||||||
|
tc.assertIn("forq", str(e))
|
||||||
|
else:
|
||||||
|
raise RuntimeError("missing exception")
|
||||||
|
spot.containment_select_version("forq")
|
||||||
|
tc.assertTrue(spot.contains(tba, tgba)) # does not call contains_forq
|
||||||
|
try:
|
||||||
|
spot.contains_forq(tba, tgba) # because contains_forq wants Büchi
|
||||||
|
except RuntimeError as e:
|
||||||
|
tc.assertIn("Büchi", str(e))
|
||||||
|
else:
|
||||||
|
raise RuntimeError("missing exception")
|
||||||
|
|
||||||
|
# This shows that exclusive word also depend on
|
||||||
|
# containment_select_version()
|
||||||
|
tc.assertEqual(str(one.exclusive_word(both)), "!a & !b; cycle{a}")
|
||||||
|
spot.containment_select_version("default")
|
||||||
|
tc.assertEqual(str(one.exclusive_word(both)), "cycle{a}")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue