Preliminary implementation of a tool to generate some interesting

families of LTL formulae.

* src/ltltest/genltl.cc: New file.  Based on five classes of
formulae defined in a paper by Cichón, Czubak, and Jasiński.
* src/ltltest/Makefile.am (noinst_PROGRAMS): Build genltl.
This commit is contained in:
Alexandre Duret-Lutz 2010-12-03 18:53:00 +01:00
parent ac9d0a502a
commit 437af50afe
4 changed files with 285 additions and 13 deletions

View file

@ -21,3 +21,4 @@ randltl
*.dot
reductau
reductaustr
genltl

View file

@ -1,4 +1,4 @@
## Copyright (C) 2009 Laboratoire de Recherche et Développement
## Copyright (C) 2009, 2010 Laboratoire de Recherche et Développement
## de l'Epita (LRDE).
## Copyright (C) 2003, 2004, 2005, 2006 Laboratoire d'Informatique de
## Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
@ -43,6 +43,7 @@ check_PROGRAMS = \
tunenoform
noinst_PROGRAMS = \
genltl \
randltl
equals_SOURCES = equals.cc

261
src/ltltest/genltl.cc Normal file
View file

@ -0,0 +1,261 @@
// Copyright (C) 2010 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#include <cassert>
#include <iostream>
#include <sstream>
#include <set>
#include <string>
#include <cstdlib>
#include <cstring>
#include "ltlast/allnodes.hh"
#include "ltlvisit/tostring.hh"
#include "ltlenv/defaultenv.hh"
using namespace spot;
using namespace spot::ltl;
environment& env(default_environment::instance());
// The five first classes defined here come from the following paper:
//
// @InProceedings{cichon.09.depcos,
// author = {Jacek Cicho{\'n} and Adam Czubak and Andrzej Jasi{\'n}ski},
// title = {Minimal {B\"uchi} Automata for Certain Classes of {LTL} Formulas},
// booktitle = {Proceedings of the Fourth International Conference on
// Dependability of Computer Systems},
// pages = {17--24},
// year = 2009,
// publisher = {IEEE Computer Society},
// }
void
syntax(char* prog)
{
std::cerr << "Usage: "<< prog << " [-s] F N" << std::endl
<< std::endl
<< "-s output using Spin's syntax" << std::endl
<< "F specifies the familly of LTL formula to build" << std::endl
<< "N is the size parameter of the familly" << std::endl
<< std::endl
<< "Classes available (F):" << std::endl
<< " 1: F(p1&F(p2&F(p3&...F(pn)))) & F(q1&F(q2&F(q3&...F(qn))))"
<< std::endl
<< " 2: p&X(p&X(p&...X(p)))) & X(q&F(q&F(q&...F(q))))"
<< std::endl
<< " 3: p&(Xp)&(XXp)&...(X...X(p)) & p&(Xq)&(XXq)&...(X...X(q))"
<< std::endl
<< " 4: GF(p1)&GF(p2)&...&GF(pn)"
<< std::endl
<< " 5: FG(p1)|GF(p2)|...|GF(pn)"
<< std::endl;
exit(2);
}
int
to_int(const char* s)
{
char* endptr;
int res = strtol(s, &endptr, 10);
if (*endptr)
{
std::cerr << "Failed to parse `" << s << "' as an integer." << std::endl;
exit(1);
}
return res;
}
// F(p_1 & F(p_2 & F(p_3 & ... F(p_n))))
formula* E_n(std::string name, int n)
{
if (n <= 0)
return constant::true_instance();
formula* result = 0;
for (; n > 0; --n)
{
std::ostringstream p;
p << name << n;
formula* f = env.require(p.str());
if (result)
result = multop::instance(multop::And, f, result);
else
result = f;
result = unop::instance(unop::F, result);
}
return result;
}
// p & X(p & X(p & ... X(p)))
formula* phi_n(std::string name, int n)
{
if (n <= 0)
return constant::true_instance();
formula* result = 0;
formula* p = env.require(name);
for (; n > 0; --n)
{
if (result)
result =
multop::instance(multop::And, p->clone(),
unop::instance(unop::X, result));
else
result = p;
}
return result;
}
formula* N_n(std::string name, int n)
{
return unop::instance(unop::F, phi_n(name, n));
}
// p & X(p) & XX(p) & XXX(p) & ... X^n(p)
formula* phi_prime_n(std::string name, int n)
{
if (n <= 0)
return constant::true_instance();
formula* result = 0;
formula* p = env.require(name);
for (; n > 0; --n)
{
if (result)
{
p = unop::instance(unop::X, p->clone());
result = multop::instance(multop::And, result, p);
}
else
{
result = p;
}
}
return result;
}
formula* N_prime_n(std::string name, int n)
{
return unop::instance(unop::F, phi_prime_n(name, n));
}
// GF(p_1) | GF(p_2) | ... | GF(p_n)
formula* FG_n(std::string name, int n)
{
if (n <= 0)
return constant::true_instance();
formula* result = 0;
for (int i = 1; i <= n; ++i)
{
std::ostringstream p;
p << name << i;
formula* f = unop::instance(unop::G,
unop::instance(unop::F,
env.require(p.str())));
if (result)
result = multop::instance(multop::And, f, result);
else
result = f;
}
return result;
}
// FG(p_1) | FG(p_2) | ... | FG(p_n)
formula* GF_n(std::string name, int n)
{
if (n <= 0)
return constant::false_instance();
formula* result = 0;
for (int i = 1; i <= n; ++i)
{
std::ostringstream p;
p << name << i;
formula* f = unop::instance(unop::F,
unop::instance(unop::G,
env.require(p.str())));
if (result)
result = multop::instance(multop::Or, f, result);
else
result = f;
}
return result;
}
int
main(int argc, char** argv)
{
bool spin_syntax = false;
if (argc >= 2 && !strcmp(argv[1], "-s"))
{
spin_syntax = true;
--argc;
++argv;
}
if (argc != 3)
syntax(argv[0]);
int f = to_int(argv[1]);
int n = to_int(argv[2]);
formula* res = 0;
switch (f)
{
case 1:
res = multop::instance(multop::And, E_n("p", n), E_n("q", n));
break;
case 2:
res = multop::instance(multop::And, N_n("p", n), N_n("q", n));
break;
case 3:
res = multop::instance(multop::And, N_prime_n("p", n), N_prime_n("q", n));
break;
case 4:
res = FG_n("p", n);
break;
case 5:
res = GF_n("p", n);
break;
default:
std::cerr << "Unknown familly " << f << std::endl;
break;
}
if (spin_syntax)
to_spin_string(res, std::cout, true) << std::endl;
else
to_string(res, std::cout, true) << std::endl;
res->destroy();
return 0;
}