Commit 75990063 authored by Florian Renkin's avatar Florian Renkin

Moved IAR and the new version of to_parity in toparity.cc

* python/spot/__init__.py: Use keyword arguments in to_parity()
* python/spot/impl.i: remove useless includes.
* spot/twaalgos/car.cc, spot/twaalgos/car.hh,
spot/twaalgos/rabin2parity.cc, spot/twaalgos/rabin2parity.hh,
tests/Makefile.am, spot/twaalgos/Makefile.am:
content moved to toparity.
* spot/twaalgos/postproc.cc: Use the new version of to_parity in
postprocessor::run.
* spot/twaalgos/toparity.cc, spot/twaalgos/toparity.hh: Add the
content of rabin2parity and car.
* tests/python/car.py, tests/python/toparity.py: Moved all tests
from car.py to toparity.py.
* tests/python/except.py: Change iar() to iar_old().
parent dddc7920
......@@ -1290,3 +1290,30 @@ class scc_and_mark_filter:
def __exit__(self, exc_type, exc_value, traceback):
self.restore_acceptance()
def to_parity(aut, **kwargs):
option = car_option()
if "search_ex" in kwargs:
option.search_ex = kwargs.get("search_ex")
if "use_last" in kwargs:
option.use_last = kwargs.get("use_last")
if "force_order" in kwargs:
option.force_order = kwargs.get("force_order")
if "partial_degen" in kwargs:
option.partial_degen = kwargs.get("partial_degen")
if "acc_clean" in kwargs:
option.acc_clean = kwargs.get("acc_clean")
if "parity_equiv" in kwargs:
option.parity_equiv = kwargs.get("parity_equiv")
if "parity_prefix" in kwargs:
option.parity_prefix = kwargs.get("parity_prefix")
if "rabin_to_buchi" in kwargs:
option.rabin_to_buchi = kwargs.get("rabin_to_buchi")
if "reduce_col_deg" in kwargs:
option.reduce_col_deg = kwargs.get("reduce_col_deg")
if "propagate_col" in kwargs:
option.propagate_col = kwargs.get("propagate_col")
if "pretty_print" in kwargs:
option.pretty_print = kwargs.get("pretty_print")
return impl.to_parity(aut, option)
......@@ -160,9 +160,7 @@
#include <spot/twaalgos/relabel.hh>
#include <spot/twaalgos/word.hh>
#include <spot/twaalgos/are_isomorphic.hh>
#include <spot/twaalgos/rabin2parity.hh>
#include <spot/twaalgos/toparity.hh>
#include <spot/twaalgos/car.hh>
#include <spot/parseaut/public.hh>
......@@ -682,9 +680,7 @@ def state_is_accepting(self, src) -> "bool":
%include <spot/twaalgos/word.hh>
%template(list_bdd) std::list<bdd>;
%include <spot/twaalgos/are_isomorphic.hh>
%include <spot/twaalgos/rabin2parity.hh>
%include <spot/twaalgos/toparity.hh>
%include <spot/twaalgos/car.hh>
%pythonprepend spot::twa::dtwa_complement %{
from warnings import warn
......
......@@ -59,7 +59,6 @@ twaalgos_HEADERS = \
isunamb.hh \
isweakscc.hh \
langmap.hh \
car.hh \
lbtt.hh \
ltl2taa.hh \
ltl2tgba_fm.hh \
......@@ -72,7 +71,6 @@ twaalgos_HEADERS = \
postproc.hh \
powerset.hh \
product.hh \
rabin2parity.hh \
randomgraph.hh \
randomize.hh \
reachiter.hh \
......@@ -129,7 +127,6 @@ libtwaalgos_la_SOURCES = \
isunamb.cc \
isweakscc.cc \
langmap.cc \
car.cc \
lbtt.cc \
ltl2taa.cc \
ltl2tgba_fm.cc \
......@@ -143,7 +140,6 @@ libtwaalgos_la_SOURCES = \
postproc.cc \
powerset.cc \
product.cc \
rabin2parity.cc \
randomgraph.cc \
randomize.cc \
reachiter.cc \
......
This diff is collapsed.
// -*- coding: utf-8 -*-
// Copyright (C) 2012-2019 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/>.
#pragma once
#include <spot/twa/twagraph.hh>
namespace spot
{
struct car_option
{
bool search_ex = true;
bool use_last = true;
bool force_order = true;
bool partial_degen = true;
bool acc_clean = true;
bool parity_equiv = true;
bool parity_prefix = true;
bool rabin_to_buchi = true;
bool reduce_col_deg = false;
bool propagate_col = true;
bool pretty_print = true;
};
/// \ingroup twa_acc_transform
/// \brief Take an automaton with any acceptance condition and return an
/// equivalent parity automaton.
///
/// The parity condition of the returned automaton is max even or
/// max odd.
/// If \a search_ex is true, when we move several elements, we
/// try to find an order such that the new permutation already exists.
/// If \a partial_degen is true, we apply a partial degeneralization to remove
// occurences of Fin | Fin and Inf & Inf.
/// If \a scc_acc_clean is true, we remove for each SCC the colors that don't
// appear.
/// If \a parity_equiv is true, we check if there exists a permutations of
// colors such that the acceptance
/// condition is a partity condition.
/// If \a use_last is true, we use the most recent state when looking for an
// existing state.
/// If \a pretty_print is true, we give a name to the states describing the
// state of the aut_ and the permutation.
SPOT_API twa_graph_ptr
remove_false_transitions(const twa_graph_ptr a);
SPOT_API twa_graph_ptr
to_parity(const twa_graph_ptr &aut, const car_option options = car_option());
} // namespace spot
\ No newline at end of file
......@@ -38,8 +38,8 @@
#include <spot/twaalgos/alternation.hh>
#include <spot/twaalgos/parity.hh>
#include <spot/twaalgos/cobuchi.hh>
#include <spot/twaalgos/rabin2parity.hh>
#include <spot/twaalgos/cleanacc.hh>
#include <spot/twaalgos/toparity.hh>
namespace spot
{
......@@ -280,7 +280,7 @@ namespace spot
twa_graph_ptr b = nullptr;
if (want_parity && is_deterministic(a) &&
!a->acc().is_generalized_buchi())
b = iar_maybe(a);
b = to_parity(a);
// possible only if a was deterministic and (Rabin-like or Streett-like)
// and we want parity and a is not a TGBA
// NB: on a TGBA, degeneralization is better than IAR
......
This diff is collapsed.
// -*- coding: utf-8 -*-
// Copyright (C) 2017-2018 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/>.
#pragma once
#include <spot/twa/twagraph.hh>
namespace spot
{
/// \ingroup twa_acc_transform
/// \brief Turn a Rabin-like or Streett-like automaton into a parity automaton
/// based on the index appearence record (IAR)
///
/// If the input automaton has n states and k pairs, the output automaton has
/// at most k!*n states and 2k+1 colors. If the input automaton is
/// deterministic, the output automaton is deterministic as well, which is the
/// intended use case for this function. If the input automaton is
/// non-deterministic, the result is still correct, but way larger than an
/// equivalent Büchi automaton.
/// If the input automaton is Rabin-like (resp. Streett-like), the output
/// automaton has max odd (resp. min even) acceptance condition.
/// Details on the algorithm can be found in:
/// https://arxiv.org/pdf/1701.05738.pdf (published at TACAS 2017)
///
/// Throws an std::runtime_error if the input is neither Rabin-like nor
/// Street-like.
SPOT_API
twa_graph_ptr
iar(const const_twa_graph_ptr& aut, bool pretty_print = false);
/// \ingroup twa_acc_transform
/// \brief Turn a Rabin-like or Streett-like automaton into a parity automaton
/// based on the index appearence record (IAR)
///
/// Returns nullptr if the input automaton is neither Rabin-like nor
/// Streett-like, and calls spot::iar() otherwise.
SPOT_API
twa_graph_ptr
iar_maybe(const const_twa_graph_ptr& aut, bool pretty_print = false);
}
This diff is collapsed.
// -*- coding: utf-8 -*-
// Copyright (C) 2018 Laboratoire de Recherche et Développement
// de l'Epita.
// Copyright (C) 2012-2020 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
//
......@@ -23,11 +23,91 @@
namespace spot
{
// The version that combines CAR, IAR and multiple optimizations.
struct car_option
{
bool search_ex = true;
bool use_last = true;
bool force_order = true;
bool partial_degen = true;
bool acc_clean = true;
bool parity_equiv = true;
bool parity_prefix = true;
bool rabin_to_buchi = true;
bool reduce_col_deg = false;
bool propagate_col = true;
bool pretty_print = false;
};
/// \ingroup twa_acc_transform
/// \brief Take an automaton with any acceptance condition and return an
/// equivalent parity automaton.
///
/// The parity condition of the returned automaton is max even or
/// max odd.
/// If \a search_ex is true, when we move several elements, we
/// try to find an order such that the new permutation already exists.
/// If \a partial_degen is true, we apply a partial degeneralization to remove
// occurences of Fin | Fin and Inf & Inf.
/// If \a scc_acc_clean is true, we remove for each SCC the colors that don't
// appear.
/// If \a parity_equiv is true, we check if there exists a permutations of
// colors such that the acceptance
/// condition is a partity condition.
/// If \a use_last is true, we use the most recent state when looking for an
// existing state.
/// If \a pretty_print is true, we give a name to the states describing the
// state of the aut_ and the permutation.
SPOT_API twa_graph_ptr
remove_false_transitions(const twa_graph_ptr a);
SPOT_API twa_graph_ptr
to_parity(const twa_graph_ptr &aut, const car_option options = car_option());
// Old version of CAR
/// \ingroup twa_acc_transform
/// \brief Take an automaton with any acceptance condition and return an
/// equivalent parity automaton.
///
/// The parity condition of the returned automaton is max even.
SPOT_API twa_graph_ptr
to_parity(const const_twa_graph_ptr& aut, bool pretty_print=false);
}
to_parity_old(const const_twa_graph_ptr& aut, bool pretty_print=false);
// Old version of IAR
/// \ingroup twa_acc_transform
/// \brief Turn a Rabin-like or Streett-like automaton into a parity automaton
/// based on the index appearence record (IAR)
///
/// If the input automaton has n states and k pairs, the output automaton has
/// at most k!*n states and 2k+1 colors. If the input automaton is
/// deterministic, the output automaton is deterministic as well, which is the
/// intended use case for this function. If the input automaton is
/// non-deterministic, the result is still correct, but way larger than an
/// equivalent Büchi automaton.
/// If the input automaton is Rabin-like (resp. Streett-like), the output
/// automaton has max odd (resp. min even) acceptance condition.
/// Details on the algorithm can be found in:
/// https://arxiv.org/pdf/1701.05738.pdf (published at TACAS 2017)
///
/// Throws an std::runtime_error if the input is neither Rabin-like nor
/// Street-like.
SPOT_API
twa_graph_ptr
iar_old(const const_twa_graph_ptr& aut, bool pretty_print = false);
/// \ingroup twa_acc_transform
/// \brief Turn a Rabin-like or Streett-like automaton into a parity automaton
/// based on the index appearence record (IAR)
///
/// Returns nullptr if the input automaton is neither Rabin-like nor
/// Streett-like, and calls spot::iar() otherwise.
SPOT_API
twa_graph_ptr
iar_maybe_old(const const_twa_graph_ptr& aut, bool pretty_print = false);
} // namespace spot
\ No newline at end of file
......@@ -373,7 +373,6 @@ TESTS_python = \
python/bdditer.py \
python/bddnqueen.py \
python/bugdet.py \
python/car.py \
python/complement_semidet.py \
python/declenv.py \
python/decompose_scc.py \
......
#!/usr/bin/python3
# -*- mode: python; coding: utf-8 -*-
# Copyright (C) 2018, 2019 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/>.
import spot
no_option = spot.car_option()
no_option.search_ex = False
no_option.use_last = False
no_option.force_order = False
no_option.partial_degen = False
no_option.acc_clean = False
no_option.parity_equiv = False
no_option.parity_prefix = False
no_option.rabin_to_buchi = False
no_option.propagate_col = False
acc_clean_search_opt = spot.car_option()
acc_clean_search_opt.force_order = False
acc_clean_search_opt.partial_degen = False
acc_clean_search_opt.parity_equiv = False
acc_clean_search_opt.parity_prefix = False
acc_clean_search_opt.rabin_to_buchi = False
acc_clean_search_opt.propagate_col = False
partial_degen_opt = spot.car_option()
partial_degen_opt.search_ex = False
partial_degen_opt.force_order = False
partial_degen_opt.parity_equiv = False
partial_degen_opt.parity_prefix = False
partial_degen_opt.rabin_to_buchi = False
partial_degen_opt.propagate_col = False
parity_equiv_opt = spot.car_option()
parity_equiv_opt.search_ex = False
parity_equiv_opt.use_last = False
parity_equiv_opt.force_order = False
parity_equiv_opt.partial_degen = False
parity_equiv_opt.parity_prefix = False
parity_equiv_opt.rabin_to_buchi = False
parity_equiv_opt.propagate_col = False
rab_to_buchi_opt = spot.car_option()
rab_to_buchi_opt.use_last = False
rab_to_buchi_opt.force_order = False
rab_to_buchi_opt.partial_degen = False
rab_to_buchi_opt.parity_equiv = False
rab_to_buchi_opt.parity_prefix = False
rab_to_buchi_opt.propagate_col = False
# Force to use CAR or IAR for each SCC
use_car_opt = spot.car_option()
use_car_opt.partial_degen = False
use_car_opt.parity_equiv = False
use_car_opt.parity_prefix = False
use_car_opt.rabin_to_buchi = False
use_car_opt.propagate_col = False
all_opt = spot.car_option()
all_opt.pretty_print = True
options = [
no_option,
acc_clean_search_opt,
partial_degen_opt,
parity_equiv_opt,
rab_to_buchi_opt,
use_car_opt,
spot.car_option(),
]
i = 1
def test(aut):
global i
for opt in options:
try:
p = spot.to_parity(aut, opt)
assert(spot.are_equivalent(aut, p))
except:
# Are equivalent can raise exception
assert(False)
test(spot.automaton("""HOA: v1
name: "(FGp0 & ((XFp0 & F!p1) | F(Gp1 & XG!p0))) | G(F!p0 & (XFp0 | F!p1) &
F(Gp1 | G!p0))"
States: 14
Start: 0
AP: 2 "p1" "p0"
Acceptance: 6 (Fin(0) & Fin(1)) | ((Fin(4)|Fin(5)) & (Inf(2)&Inf(3)))
properties: trans-labels explicit-labels trans-acc complete
properties: deterministic
--BODY--
State: 0
[!0] 1
[0] 2
State: 1
[!0&!1] 1 {0 1 2 3 5}
[0&!1] 3
[!0&1] 4
[0&1] 5
State: 2
[0&!1] 2 {1}
[!0&1] 4
[!0&!1] 6
[0&1] 7
State: 3
[0&!1] 3 {1 3}
[!0&1] 4
[!0&!1] 6 {0 1 2 3 5}
[0&1] 8
State: 4
[!0&!1] 4 {1 2 3 5}
[!0&1] 4 {2 4 5}
[0&!1] 5 {1 3}
[0&1] 5 {4}
State: 5
[!0&1] 4 {2 4 5}
[0&!1] 5 {1 3}
[0&1] 8 {2 4}
[!0&!1] 9 {1 2 3 5}
State: 6
[0&!1] 3 {1 3}
[!0&1] 4
[0&1] 5
[!0&!1] 10
State: 7
[!0&1] 4
[0&!1] 7 {1 3}
[!0&!1] 11
[0&1] 12 {0 4}
State: 8
[!0&1] 4 {2 4 5}
[0&1] 5 {4}
[0&!1] 8 {1 3}
[!0&!1] 11 {1 3 5}
State: 9
[!0&1] 4 {2 4 5}
[0&!1] 5 {1 3}
[0&1] 5 {4}
[!0&!1] 11 {1 3 5}
State: 10
[!0&1] 4
[0&1] 8
[!0&!1] 10 {0 1 2 3 5}
[0&!1] 13 {1 2 3}
State: 11
[!0&1] 4 {2 4 5}
[0&!1] 8 {1 2 3}
[0&1] 8 {2 4}
[!0&!1] 11 {1 2 3 5}
State: 12
[!0&1] 4
[0&1] 7 {0 2 4}
[!0&!1] 9
[0&!1] 12 {1 3}
State: 13
[!0&1] 4
[0&1] 5
[!0&!1] 10 {0 1 3 5}
[0&!1] 13 {1 3}
--END--"""))
test(spot.automaton("""
HOA: v1
States: 2
Start: 0
AP: 2 "p0" "p1"
Acceptance: 5 (Inf(0)&Inf(1)) | ((Fin(2)|Fin(3)) & Fin(4))
--BODY--
State: 0
[!0 & 1] 0 {2 3}
[!0 & !1] 0 {3}
[0] 1
State: 1
[0&1] 1 {1 2 4}
[0&!1] 1 {4}
[!0&1] 1 {0 1 2 3}
[!0&!1] 1 {0 3}
--END--"""))
test(spot.automaton("""
HOA: v1 States: 6 Start: 0 AP: 2 "p0" "p1" Acceptance: 6 Inf(5) |
Fin(2) | Inf(1) | (Inf(0) & Fin(3)) | Inf(4) properties: trans-labels
explicit-labels trans-acc --BODY-- State: 0 [0&1] 2 {4 5} [0&1] 4 {0 4}
[!0&!1] 3 {3 5} State: 1 [0&!1] 3 {1 5} [!0&!1] 5 {0 1} State: 2 [!0&!1]
0 {0 3} [0&!1] 1 {0} State: 3 [!0&1] 4 {1 2 3} [0&1] 3 {3 4 5} State:
4 [!0&!1] 1 {2 4} State: 5 [!0&1] 4 --END--
"""))
for f in spot.randltl(15, 2000):
test(spot.translate(f, "det", "G"))
for f in spot.randltl(5, 25000):
test(spot.translate(f))
test(spot.translate('!(GFa -> (GFb & GF(!b & !Xb)))', 'gen', 'det'))
test(spot.automaton("""
HOA: v1
States: 4
Start: 0
AP: 2 "p0" "p1"
Acceptance: 6
((Fin(1) | Inf(2)) & Inf(5)) | (Fin(0) & (Fin(1) | (Fin(3) & Inf(4))))
properties: trans-labels explicit-labels trans-acc complete
properties: deterministic
--BODY--
State: 0
[!0&!1] 0 {2}
[0&1] 1 {0 5}
[0&!1] 1 {0 2 5}
[!0&1] 2 {1}
State: 1
[0&1] 1 {0}
[!0&!1] 1 {2}
[0&!1] 1 {0 2}
[!0&1] 2 {1}
State: 2
[!0&!1] 0 {2 3}
[0&!1] 0 {0 2 3 5}
[!0&1] 2 {1 4}
[0&1] 3 {0 5}
State: 3
[!0&!1] 0 {2 3}
[0&!1] 0 {0 2 3 5}
[!0&1] 2 {1 4}
[0&1] 3 {0}
--END--
"""))
test(spot.automaton("""
HOA: v1
States: 5
Start: 0
AP: 2 "p1" "p0"
Acceptance: 5 (Fin(0) & Fin(1)) | (Fin(3) & (Inf(2)&Inf(4)))
properties: trans-labels explicit-labels trans-acc complete
properties: deterministic
--BODY--
State: 0
[!0] 1
[0] 2
State: 1
[!0&!1] 1 {0 1}
[!0&1] 3
[0] 4
State: 2
[!0&1] 1
[0&!1] 2
[0&1] 2 {0 1 2 4}
[!0&!1] 3
State: 3
[!0&1] 3 {1 2 3}
[!0&!1] 3 {4}
[0&!1] 4 {3}
[0&1] 4 {1 2 3}
State: 4
[!0&!1] 3 {3}
[!0&1] 3 {1 2 3}
[0&!1] 4
[0&1] 4 {1 2 4}
--END--
"""))
test(spot.automaton("""
HOA: v1
States: 2
Start: 0
AP: 2 "p1" "p0"
Acceptance: 5 (Fin(0) & (Fin(3)|Fin(4)) & (Inf(1)&Inf(2))) | Inf(3)
properties: trans-labels explicit-labels trans-acc complete
properties: deterministic stutter-invariant
--BODY--
State: 0
[0&!1] 0 {2 3}
[!0&!1] 0 {2 3 4}
[!0&1] 1
[0&1] 1 {2 4}
State: 1
[!0&!1] 0 {0 2 3 4}
[!0&1] 1 {1}
[0&!1] 1 {2 3}
[0&1] 1 {1 2 4}
--END--
"""))
......@@ -33,7 +33,7 @@ def report_missing_exception():
aut = spot.translate('GFa & GFb & GFc')
aut.set_acceptance(spot.acc_cond("parity min even 4"))
try:
spot.iar(aut)
spot.iar_old(aut)
except RuntimeError as e:
assert 'iar() expects Rabin-like or Streett-like input' in str(e)
else:
......
......@@ -20,6 +20,304 @@
import spot
# Tests for the new version of to_parity