diff --git a/src/tgbatest/.gitignore b/src/tgbatest/.gitignore
index 7ea3d63dc..af7797635 100644
--- a/src/tgbatest/.gitignore
+++ b/src/tgbatest/.gitignore
@@ -6,6 +6,7 @@ defs
.deps
*.dot
eltl2tgba
+emptchk
expldot
explicit
explicit2
diff --git a/src/tgbatest/Makefile.am b/src/tgbatest/Makefile.am
index 2efd6a40f..a5e320ab0 100644
--- a/src/tgbatest/Makefile.am
+++ b/src/tgbatest/Makefile.am
@@ -35,6 +35,7 @@ check_PROGRAMS = \
complement \
checkpsl \
checkta \
+ emptchk \
expldot \
explprod \
intvcomp \
@@ -52,6 +53,7 @@ bitvect_SOURCES = bitvect.cc
checkpsl_SOURCES = checkpsl.cc
checkta_SOURCES = checkta.cc
complement_SOURCES = complementation.cc
+emptchk_SOURCES = emptchk.cc
expldot_SOURCES = powerset.cc
expldot_CXXFLAGS = -DDOTTY
explprod_SOURCES = explprod.cc
diff --git a/src/tgbatest/emptchk.cc b/src/tgbatest/emptchk.cc
new file mode 100644
index 000000000..1a1f70256
--- /dev/null
+++ b/src/tgbatest/emptchk.cc
@@ -0,0 +1,221 @@
+// -*- coding: utf-8 -*-
+// Copyright (C) 2014 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 .
+
+#include
+#include
+#include
+#include
+#include
+#include "ltlparse/public.hh"
+#include "ltlast/allnodes.hh"
+#include "tgba/futurecondcol.hh"
+#include "tgbaalgos/ltl2tgba_fm.hh"
+#include "tgbaalgos/ltl2taa.hh"
+#include "tgbaalgos/sccfilter.hh"
+#include "tgbaalgos/degen.hh"
+#include "tgba/tgbaproduct.hh"
+#include "tgbaalgos/gtec/gtec.hh"
+#include "tgbaalgos/dotty.hh"
+#include "tgbaalgos/dupexp.hh"
+#include "tgbaalgos/emptiness.hh"
+
+void
+syntax(char* prog)
+{
+ std::cerr << prog << " file" << std::endl;
+ exit(2);
+}
+
+int
+main(int argc, char** argv)
+{
+ if (argc != 2)
+ syntax(argv[0]);
+ std::ifstream input(argv[1]);
+ if (!input)
+ {
+ std::cerr << "failed to open " << argv[1] << '\n';
+ return 2;
+ }
+
+
+ auto d = spot::make_bdd_dict();
+
+ std::string s;
+ unsigned line = 0;
+ while (std::getline(input, s))
+ {
+ ++line;
+ std::cout << "========================================================\n";
+ std::cout << line << ": " << s << '\n';
+ if (s.empty() || s[0] == '#') // Skip comments
+ continue;
+
+ std::vector tokens;
+ {
+ std::istringstream ss(s);
+ std::string form;
+ while (std::getline(ss, form, ','))
+ {
+ std::string tmp;
+ while (form.size() > 0 && form.back() == '\\'
+ && std::getline(ss, tmp, ','))
+ {
+ form.back() = ',';
+ form += tmp;
+ }
+ tokens.push_back(form);
+ }
+ }
+
+ if (tokens.size() != 2)
+ {
+ std::cerr << "Expecting two tokens on input line.\n";
+ exit(2);
+ }
+
+ int runs = atoi(tokens[0].c_str());
+
+ spot::ltl::parse_error_list pe;
+ auto f = spot::ltl::parse(tokens[1], pe);
+ if (spot::ltl::format_parse_errors(std::cerr, tokens[1], pe))
+ return 2;
+
+ auto d = spot::make_bdd_dict();
+
+ // Build many different automata from this formula.
+ spot::const_tgba_ptr aut[4];
+ {
+ auto a = spot::ltl_to_taa(f, d);
+ aut[0] = a;
+ aut[1] = spot::degeneralize_tba(a);
+ }
+ {
+ auto a = spot::ltl_to_tgba_fm(f, d);
+ aut[2] = a;
+ aut[3] = spot::degeneralize(a);
+ }
+
+ const char* algos[] = {
+ "Cou99", "Cou99(shy)",
+ "CVWY90", "CVWY90(bsh=10M)", "CVWY90(repeated)",
+ "SE05", "SE05(bsh=10M)", "SE05(repeated)",
+ "Tau03_opt", "GV04",
+ };
+
+ for (auto& algo: algos)
+ {
+ const char* err;
+ auto i = spot::emptiness_check_instantiator::construct(algo, &err);
+ if (!i)
+ {
+ std::cerr << "Failed to parse `" << err << '\'' << std::endl;
+ exit(2);
+ }
+
+ for (unsigned j = 0; j < sizeof(aut)/sizeof(*aut); ++j)
+ {
+ auto a = aut[j];
+ std::cout << "** Testing aut[" << j << "] using " << algo << '\n';
+ unsigned n_acc = a->number_of_acceptance_conditions();
+ unsigned n_max = i->max_acceptance_conditions();
+ if (n_max < n_acc)
+ {
+ std::cout << "Skipping because automaton has " << n_acc
+ << " acceptance sets, and " << algo
+ << " accepts at most " << n_max << ".\n";
+ continue;
+ }
+ unsigned n_min = i->min_acceptance_conditions();
+ if (n_min > n_acc)
+ {
+ std::cout << "Skipping because automaton has " << n_acc
+ << " acceptance sets, and " << algo
+ << " wants at least " << n_min << ".\n";
+ continue;
+ }
+
+ auto ec = i->instantiate(a);
+ bool search_many = i->options().get("repeated");
+ assert(ec);
+ int ce_found = 0;
+ do
+ {
+ auto res = ec->check();
+ if (res)
+ {
+ ++ce_found;
+ std::cout << ce_found << " counterexample found\n";
+ auto run = res->accepting_run();
+ if (run)
+ {
+ auto ar = spot::tgba_run_to_tgba(a, run);
+ spot::dotty_reachable(std::cout, ar, false);
+ delete run;
+ }
+ std::cout << '\n';
+ if (runs == 0)
+ {
+ std::cerr << "ERROR: Expected no counterexample.\n";
+ exit(1);
+ }
+ delete res;
+ }
+ else
+ {
+ if (ce_found)
+ std::cout << "No more counterexample found.\n\n";
+ else
+ std::cout << "No counterexample found.\n\n";
+ break;
+ }
+ }
+ while (search_many);
+
+ // The expected number of runs is only for TAA translations
+ if (search_many && runs > ce_found && j < 2)
+ {
+ std::cerr << "ERROR: only " << ce_found
+ << " counterexamples founds, expected at least "
+ << runs << '\n';
+ exit(1);
+ }
+ if (!search_many && ec->safe() && runs && !ce_found)
+ {
+ std::cerr << "ERROR: expected a counterexample.\n";
+ exit(1);
+ }
+
+ delete ec;
+ }
+ delete i;
+ }
+ f->destroy();
+ }
+
+ spot::ltl::atomic_prop::dump_instances(std::cerr);
+ spot::ltl::unop::dump_instances(std::cerr);
+ spot::ltl::binop::dump_instances(std::cerr);
+ spot::ltl::multop::dump_instances(std::cerr);
+ assert(spot::ltl::atomic_prop::instance_count() == 0);
+ assert(spot::ltl::unop::instance_count() == 0);
+ assert(spot::ltl::binop::instance_count() == 0);
+ assert(spot::ltl::multop::instance_count() == 0);
+ return 0;
+}
diff --git a/src/tgbatest/emptchk.test b/src/tgbatest/emptchk.test
index 7cbbc443e..1c0c5a705 100755
--- a/src/tgbatest/emptchk.test
+++ b/src/tgbatest/emptchk.test
@@ -26,74 +26,19 @@
set -e
-expect_ce_do()
-{
- run 0 ../ltl2tgba "$@"
- run 0 ../ltl2tgba -g "$@"
-}
+cat > emptchk.txt < (F x))
+0, Xa && (!a U b) && !b && X!b
+0, (a U !b) && Gb
+EOF
-expect_ce()
-{
- expect_ce_do -CR -e -taa "$1"
- expect_ce_do -CR -e -taa -DT "$1"
- expect_ce_do -CR -e -f "$1"
- expect_ce_do -CR -e -f -DT "$1"
- expect_ce_do -CR -e'Cou99(shy)' -taa "$1"
- expect_ce_do -CR -e'Cou99(shy)' -taa -DT "$1"
- expect_ce_do -CR -e'Cou99(shy)' -f "$1"
- expect_ce_do -CR -e'Cou99(shy)' -f -DT "$1"
- expect_ce_do -CR -eCVWY90 -taa "$1"
- expect_ce_do -CR -eCVWY90 -f "$1"
- run 0 ../ltl2tgba -CR -e'CVWY90(bsh=10M)' -taa "$1"
- run 0 ../ltl2tgba -CR -e'CVWY90(bsh=10M)' -f "$1"
- run 0 ../ltl2tgba -CR -eSE05 -taa "$1"
- run 0 ../ltl2tgba -CR -eSE05 -f "$1"
- run 0 ../ltl2tgba -CR -e'SE05(bsh=10M)' -taa "$1"
- run 0 ../ltl2tgba -CR -e'SE05(bsh=10M)' -f "$1"
- run 0 ../ltl2tgba -CR -eTau03_opt -f "$1"
- run 0 ../ltl2tgba -CR -eGV04 -f "$1"
- # Expect multiple accepting runs
- test `../ltl2tgba -C -e'CVWY90(repeated)' -taa "$1" |
- grep Prefix: | wc -l` -ge $2
- test `../ltl2tgba -C -e'SE05(repeated)' -taa "$1" |
- grep Prefix: | wc -l` -ge $2
-}
-
-expect_no()
-{
- run 0 ../ltl2tgba -CR -E -taa "$1"
- run 0 ../ltl2tgba -CR -E -taa -DT "$1"
- run 0 ../ltl2tgba -CR -E -f "$1"
- run 0 ../ltl2tgba -CR -E -f -DT "$1"
- run 0 ../ltl2tgba -CR -E'Cou99(shy)' -taa "$1"
- run 0 ../ltl2tgba -CR -E'Cou99(shy)' -taa -DT "$1"
- run 0 ../ltl2tgba -CR -E'Cou99(shy)' -f "$1"
- run 0 ../ltl2tgba -CR -E'Cou99(shy)' -f -DT "$1"
- run 0 ../ltl2tgba -CR -ECVWY90 -taa "$1"
- run 0 ../ltl2tgba -CR -ECVWY90 -f "$1"
- run 0 ../ltl2tgba -CR -E'CVWY90(bsh=10M)' -taa "$1"
- run 0 ../ltl2tgba -CR -E'CVWY90(bsh=10M)' -f "$1"
- run 0 ../ltl2tgba -CR -ESE05 -taa "$1"
- run 0 ../ltl2tgba -CR -ESE05 -f "$1"
- run 0 ../ltl2tgba -CR -E'SE05(bsh=10M)' -taa "$1"
- run 0 ../ltl2tgba -CR -E'SE05(bsh=10M)' -f "$1"
- run 0 ../ltl2tgba -CR -ETau03_opt -f "$1"
- run 0 ../ltl2tgba -CR -EGV04 -f "$1"
- test `../ltl2tgba -C -e'CVWY90(repeated)' -taa "!($1)" |
- grep Prefix: | wc -l` -ge $2
- test `../ltl2tgba -C -e'SE05(repeated)' -taa "!($1)" |
- grep Prefix: | wc -l` -ge $2
-}
-
-expect_ce 'a' 1
-expect_ce 'a U b' 1
-expect_ce 'X a' 1
-expect_ce 'a & b & c' 1
-expect_ce 'a | b | (c U (d & (g U (h ^ i))))' 1
-expect_ce 'Xa & (b U !a) & (b U !a)' 1
-expect_ce 'Fa & Xb & GFc & Gd' 1
-expect_ce 'Fa & Xa & GFc & Gc' 2
-expect_ce 'Fc & X(a | Xb) & GF(a | Xb) & Gc' 1
-expect_ce '!((FF a) <=> (F x))' 2
-expect_no 'Xa && (!a U b) && !b && X!b' 2
-expect_no '(a U !b) && Gb' 2
+run 0 ../emptchk emptchk.txt