autfilt: better handling of chain of products with -B
Fixes #348, reported by Jeroen Meijer. * bin/autfilt.cc: If -B is used with many --product, degeneralize intermediate products as needed. * NEWS: Mention the change. * tests/core/prodchain.test: New file. * tests/Makefile.am: Add it. * spot/twa/acc.cc, spot/twa/acc.hh: Fix reporting of overflow. * tests/core/acc.cc: Adjust.
This commit is contained in:
parent
a738801edf
commit
c87c13db67
7 changed files with 149 additions and 19 deletions
7
NEWS
7
NEWS
|
|
@ -15,6 +15,13 @@ New in spot 2.5.3.dev (not yet released)
|
||||||
- ltlcross, ltldo, and autcross learned shorthands to call
|
- ltlcross, ltldo, and autcross learned shorthands to call
|
||||||
delag, ltl2dra, ltl2dgra, and nba2dpa.
|
delag, ltl2dra, ltl2dgra, and nba2dpa.
|
||||||
|
|
||||||
|
- When autfilt is asked to build a Büchi automaton from
|
||||||
|
of a chain of many products, as in
|
||||||
|
"autfilt -B --product 1.hoa ... --product n.hoa in.hoa"
|
||||||
|
then it will automatically degeneralize the intermediate
|
||||||
|
product to avoid exceeding the number of supported
|
||||||
|
acceptance sets.
|
||||||
|
|
||||||
Library:
|
Library:
|
||||||
|
|
||||||
- You can now specify to Spot the number of acceptance marks you
|
- You can now specify to Spot the number of acceptance marks you
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@
|
||||||
#include <spot/twaalgos/cobuchi.hh>
|
#include <spot/twaalgos/cobuchi.hh>
|
||||||
#include <spot/twaalgos/cleanacc.hh>
|
#include <spot/twaalgos/cleanacc.hh>
|
||||||
#include <spot/twaalgos/contains.hh>
|
#include <spot/twaalgos/contains.hh>
|
||||||
|
#include <spot/twaalgos/degen.hh>
|
||||||
#include <spot/twaalgos/dtwasat.hh>
|
#include <spot/twaalgos/dtwasat.hh>
|
||||||
#include <spot/twaalgos/dualize.hh>
|
#include <spot/twaalgos/dualize.hh>
|
||||||
#include <spot/twaalgos/gtec/gtec.hh>
|
#include <spot/twaalgos/gtec/gtec.hh>
|
||||||
|
|
@ -634,6 +635,40 @@ ensure_deterministic(const spot::twa_graph_ptr& aut, bool nonalt = false)
|
||||||
return p.run(aut);
|
return p.run(aut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static spot::twa_graph_ptr ensure_tba(spot::twa_graph_ptr aut)
|
||||||
|
{
|
||||||
|
spot::postprocessor p;
|
||||||
|
p.set_type(spot::postprocessor::TGBA);
|
||||||
|
p.set_pref(spot::postprocessor::Any);
|
||||||
|
p.set_level(spot::postprocessor::Low);
|
||||||
|
return spot::degeneralize_tba(p.run(aut));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static spot::twa_graph_ptr
|
||||||
|
product(spot::twa_graph_ptr left, spot::twa_graph_ptr right)
|
||||||
|
{
|
||||||
|
if ((type == spot::postprocessor::BA)
|
||||||
|
&& (left->num_sets() + right->num_sets() > SPOT_NB_ACC))
|
||||||
|
{
|
||||||
|
left = ensure_tba(left);
|
||||||
|
right = ensure_tba(right);
|
||||||
|
}
|
||||||
|
return spot::product(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
static spot::twa_graph_ptr
|
||||||
|
product_or(spot::twa_graph_ptr left, spot::twa_graph_ptr right)
|
||||||
|
{
|
||||||
|
if ((type == spot::postprocessor::BA)
|
||||||
|
&& (left->num_sets() + right->num_sets() > SPOT_NB_ACC))
|
||||||
|
{
|
||||||
|
left = ensure_tba(left);
|
||||||
|
right = ensure_tba(right);
|
||||||
|
}
|
||||||
|
return spot::product_or(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parse_opt(int key, char* arg, struct argp_state*)
|
parse_opt(int key, char* arg, struct argp_state*)
|
||||||
{
|
{
|
||||||
|
|
@ -947,8 +982,8 @@ parse_opt(int key, char* arg, struct argp_state*)
|
||||||
if (!opt->product_and)
|
if (!opt->product_and)
|
||||||
opt->product_and = std::move(a);
|
opt->product_and = std::move(a);
|
||||||
else
|
else
|
||||||
opt->product_and = spot::product(std::move(opt->product_and),
|
opt->product_and = ::product(std::move(opt->product_and),
|
||||||
std::move(a));
|
std::move(a));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPT_PRODUCT_OR:
|
case OPT_PRODUCT_OR:
|
||||||
|
|
@ -957,8 +992,8 @@ parse_opt(int key, char* arg, struct argp_state*)
|
||||||
if (!opt->product_or)
|
if (!opt->product_or)
|
||||||
opt->product_or = std::move(a);
|
opt->product_or = std::move(a);
|
||||||
else
|
else
|
||||||
opt->product_or = spot::product_or(std::move(opt->product_or),
|
opt->product_or = ::product_or(std::move(opt->product_or),
|
||||||
std::move(a));
|
std::move(a));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPT_RANDOMIZE:
|
case OPT_RANDOMIZE:
|
||||||
|
|
@ -1410,9 +1445,9 @@ namespace
|
||||||
aut->purge_unreachable_states();
|
aut->purge_unreachable_states();
|
||||||
|
|
||||||
if (opt->product_and)
|
if (opt->product_and)
|
||||||
aut = spot::product(std::move(aut), opt->product_and);
|
aut = ::product(std::move(aut), opt->product_and);
|
||||||
if (opt->product_or)
|
if (opt->product_or)
|
||||||
aut = spot::product_or(std::move(aut), opt->product_or);
|
aut = ::product_or(std::move(aut), opt->product_or);
|
||||||
|
|
||||||
if (opt->sum_or)
|
if (opt->sum_or)
|
||||||
aut = spot::sum(std::move(aut), opt->sum_or);
|
aut = spot::sum(std::move(aut), opt->sum_or);
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,14 @@
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
void acc_cond::report_too_many_sets()
|
||||||
|
{
|
||||||
|
#define STR(x) #x
|
||||||
|
#define VALUESTR(x) STR(x)
|
||||||
|
throw std::runtime_error("Too many acceptance sets used. "
|
||||||
|
"The limit is " VALUESTR(SPOT_NB_ACC) ".");
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, spot::acc_cond::mark_t m)
|
std::ostream& operator<<(std::ostream& os, spot::acc_cond::mark_t m)
|
||||||
{
|
{
|
||||||
auto a = m;
|
auto a = m;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,11 @@ namespace spot
|
||||||
|
|
||||||
class SPOT_API acc_cond
|
class SPOT_API acc_cond
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#ifndef SWIG
|
||||||
|
private:
|
||||||
|
[[noreturn]] static void report_too_many_sets();
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
struct mark_t : public internal::_32acc<SPOT_NB_ACC == 8*sizeof(unsigned)>
|
struct mark_t : public internal::_32acc<SPOT_NB_ACC == 8*sizeof(unsigned)>
|
||||||
{
|
{
|
||||||
|
|
@ -214,24 +219,52 @@ namespace spot
|
||||||
|
|
||||||
mark_t operator<<(unsigned i) const
|
mark_t operator<<(unsigned i) const
|
||||||
{
|
{
|
||||||
return id << i;
|
try
|
||||||
|
{
|
||||||
|
return id << i;
|
||||||
|
}
|
||||||
|
catch (const std::runtime_error& e)
|
||||||
|
{
|
||||||
|
report_too_many_sets();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_t& operator<<=(unsigned i)
|
mark_t& operator<<=(unsigned i)
|
||||||
{
|
{
|
||||||
id <<= i;
|
try
|
||||||
return *this;
|
{
|
||||||
|
id <<= i;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
catch (const std::runtime_error& e)
|
||||||
|
{
|
||||||
|
report_too_many_sets();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_t operator>>(unsigned i) const
|
mark_t operator>>(unsigned i) const
|
||||||
{
|
{
|
||||||
return id >> i;
|
try
|
||||||
|
{
|
||||||
|
return id >> i;
|
||||||
|
}
|
||||||
|
catch (const std::runtime_error& e)
|
||||||
|
{
|
||||||
|
report_too_many_sets();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_t& operator>>=(unsigned i)
|
mark_t& operator>>=(unsigned i)
|
||||||
{
|
{
|
||||||
id >>= i;
|
try
|
||||||
return *this;
|
{
|
||||||
|
id >>= i;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
catch (const std::runtime_error& e)
|
||||||
|
{
|
||||||
|
report_too_many_sets();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_t strip(mark_t y) const
|
mark_t strip(mark_t y) const
|
||||||
|
|
@ -1229,7 +1262,7 @@ namespace spot
|
||||||
unsigned j = num_;
|
unsigned j = num_;
|
||||||
num_ += num;
|
num_ += num;
|
||||||
if (num_ > SPOT_NB_ACC)
|
if (num_ > SPOT_NB_ACC)
|
||||||
throw std::runtime_error("Too many acceptance sets used.");
|
report_too_many_sets();
|
||||||
all_ = all_sets_();
|
all_ = all_sets_();
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,7 @@ TESTS_twa = \
|
||||||
core/ltldo2.test \
|
core/ltldo2.test \
|
||||||
core/maskacc.test \
|
core/maskacc.test \
|
||||||
core/maskkeep.test \
|
core/maskkeep.test \
|
||||||
|
core/prodchain.test \
|
||||||
core/prodor.test \
|
core/prodor.test \
|
||||||
core/simdet.test \
|
core/simdet.test \
|
||||||
core/sim2.test \
|
core/sim2.test \
|
||||||
|
|
|
||||||
|
|
@ -189,8 +189,7 @@ int main()
|
||||||
}
|
}
|
||||||
catch (const std::runtime_error& e)
|
catch (const std::runtime_error& e)
|
||||||
{
|
{
|
||||||
if (std::strcmp(e.what(), "Too many acceptance sets used."))
|
assert(!std::strncmp(e.what(), "Too many acceptance sets used.", 30));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -200,8 +199,7 @@ int main()
|
||||||
}
|
}
|
||||||
catch (const std::runtime_error& e)
|
catch (const std::runtime_error& e)
|
||||||
{
|
{
|
||||||
if (std::strcmp(e.what(), "bit shift overflow is undefined behavior"))
|
assert(!std::strncmp(e.what(), "Too many acceptance sets used.", 30));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -211,8 +209,7 @@ int main()
|
||||||
}
|
}
|
||||||
catch (const std::runtime_error& e)
|
catch (const std::runtime_error& e)
|
||||||
{
|
{
|
||||||
if (std::strcmp(e.what(), "bit shift overflow is undefined behavior"))
|
assert(!std::strncmp(e.what(), "Too many acceptance sets used.", 30));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
49
tests/core/prodchain.test
Executable file
49
tests/core/prodchain.test
Executable file
|
|
@ -0,0 +1,49 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (C) 2018 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/>.
|
||||||
|
|
||||||
|
. ./defs
|
||||||
|
set -e
|
||||||
|
|
||||||
|
set x
|
||||||
|
shift
|
||||||
|
for i in `seq 1 42`; do
|
||||||
|
ltl2tgba "{a[*$i]}[]->GFb" > $i.hoa
|
||||||
|
done
|
||||||
|
for i in *.hoa; do
|
||||||
|
set x "$@" --product $i
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
autfilt "$@" 2> error && exit 1
|
||||||
|
grep 'Too many acceptance sets used' error
|
||||||
|
autfilt -B "$@" > result
|
||||||
|
test "127,253,508,1" = `autfilt --stats=%s,%e,%t,%a result`
|
||||||
|
|
||||||
|
set x
|
||||||
|
shift
|
||||||
|
for i in *.hoa; do
|
||||||
|
set x "$@" --product-or $i
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
shift
|
||||||
|
autfilt "$@" 2> error && exit 1
|
||||||
|
grep 'Too many acceptance sets used' error
|
||||||
|
autfilt -B "$@" > result
|
||||||
|
test "45,89,180,1" = `autfilt --stats=%s,%e,%t,%a result`
|
||||||
Loading…
Add table
Add a link
Reference in a new issue