*** empty log message ***
This commit is contained in:
parent
faf4a2af26
commit
bafc92d0b8
15 changed files with 4510 additions and 5 deletions
|
|
@ -30,15 +30,18 @@ check_SCRIPTS = defs
|
|||
# Keep this sorted alphabetically.
|
||||
check_PROGRAMS = \
|
||||
equals \
|
||||
inf \
|
||||
ltl2dot \
|
||||
ltl2text \
|
||||
lunabbrev \
|
||||
nenoform \
|
||||
reduc \
|
||||
tostring \
|
||||
tunabbrev \
|
||||
tunenoform
|
||||
tunenoform
|
||||
|
||||
equals_SOURCES = equals.cc
|
||||
inf_SOURCES = inf.cc
|
||||
ltl2dot_SOURCES = readltl.cc
|
||||
ltl2dot_CPPFLAGS = $(AM_CPPFLAGS) -DDOTTY
|
||||
ltl2text_SOURCES = readltl.cc
|
||||
|
|
@ -46,6 +49,7 @@ lunabbrev_SOURCES = equals.cc
|
|||
lunabbrev_CPPFLAGS = $(AM_CPPFLAGS) -DLUNABBREV
|
||||
nenoform_SOURCES = equals.cc
|
||||
nenoform_CPPFLAGS = $(AM_CPPFLAGS) -DNENOFORM
|
||||
reduc_SOURCES = reduc.cc
|
||||
tostring_SOURCES = tostring.cc
|
||||
tunabbrev_SOURCES = equals.cc
|
||||
tunabbrev_CPPFLAGS = $(AM_CPPFLAGS) -DTUNABBREV
|
||||
|
|
@ -57,6 +61,8 @@ EXTRA_DIST = $(TESTS)
|
|||
|
||||
# Ordered by strength of the test. Test basic features first.
|
||||
TESTS = \
|
||||
inf.test \
|
||||
reduc.test \
|
||||
parse.test \
|
||||
parseerr.test \
|
||||
equals.test \
|
||||
|
|
|
|||
2172
src/ltltest/formules.ltl
Normal file
2172
src/ltltest/formules.ltl
Normal file
File diff suppressed because it is too large
Load diff
97
src/ltltest/inf.cc
Normal file
97
src/ltltest/inf.cc
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright (C) 2003 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
// 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 <iostream>
|
||||
#include <cassert>
|
||||
#include "ltlparse/public.hh"
|
||||
#include "ltlvisit/lunabbrev.hh"
|
||||
#include "ltlvisit/tunabbrev.hh"
|
||||
#include "ltlvisit/dump.hh"
|
||||
#include "ltlvisit/nenoform.hh"
|
||||
#include "ltlvisit/destroy.hh"
|
||||
#include "ltlvisit/tostring.hh"
|
||||
#include "ltlvisit/reducform.hh"
|
||||
#include "ltlast/allnodes.hh"
|
||||
|
||||
void
|
||||
syntax(char* prog)
|
||||
{
|
||||
std::cerr << prog << " formula1 formula2?" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 3)
|
||||
syntax(argv[0]);
|
||||
|
||||
|
||||
spot::ltl::parse_error_list p1;
|
||||
spot::ltl::formula* f1 = spot::ltl::parse(argv[1], p1);
|
||||
spot::ltl::formula* f2 = NULL;
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[1], p1))
|
||||
return 2;
|
||||
|
||||
spot::ltl::parse_error_list p2;
|
||||
f2 = spot::ltl::parse(argv[2], p2);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[2], p2))
|
||||
return 2;
|
||||
|
||||
std::string f1s = spot::ltl::to_string(f1);
|
||||
std::string f2s = spot::ltl::to_string(f2);
|
||||
|
||||
int exit_return = 0;
|
||||
|
||||
std::cout << "Test f1 < f2" << std::endl;
|
||||
if (spot::ltl::inf_form(f1,f2)) {
|
||||
std::cout << f1s << " < " << f2s << std::endl;
|
||||
exit_return = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
std::cout << "Test !f1 < f2" << std::endl;
|
||||
if (spot::ltl::infneg_form(f1,f2,0)) {
|
||||
std::cout << "!(" << f1s << ") < " << f2s << std::endl;
|
||||
exit_return = 2;
|
||||
}
|
||||
|
||||
std::cout << "Test f1 < !f2" << std::endl;
|
||||
if (spot::ltl::infneg_form(f1,f2,1)) {
|
||||
std::cout << f1s << " < !(" << f2s << ")" << std::endl;
|
||||
exit_return = 3;
|
||||
}
|
||||
*/
|
||||
|
||||
spot::ltl::dump(std::cout, f1); std::cout << std::endl;
|
||||
spot::ltl::dump(std::cout, f2); std::cout << std::endl;
|
||||
|
||||
spot::ltl::destroy(f1);
|
||||
spot::ltl::destroy(f2);
|
||||
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 exit_return;
|
||||
}
|
||||
74
src/ltltest/inf.test
Executable file
74
src/ltltest/inf.test
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
#! /bin/sh
|
||||
# Copyright (C) 2003 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
# département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
# et Marie Curie.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
# Check for the reduc visitor
|
||||
|
||||
. ./defs || exit 1
|
||||
|
||||
#
|
||||
|
||||
run 1 ./inf '1' '1'
|
||||
run 1 ./inf '0' '0'
|
||||
|
||||
run 1 ./inf 'a' '1'
|
||||
run 1 ./inf 'a' 'a'
|
||||
|
||||
run 1 ./inf 'a' 'a * 1'
|
||||
|
||||
run 1 ./inf 'a * b' 'b'
|
||||
run 1 ./inf 'a * b' 'a'
|
||||
|
||||
run 1 ./inf 'a' 'a + b'
|
||||
run 1 ./inf 'b' 'a + b'
|
||||
|
||||
run 1 ./inf 'a + b' '1'
|
||||
|
||||
run 1 ./inf 'a' 'b U a'
|
||||
run 1 ./inf 'a' 'b U 1'
|
||||
run 1 ./inf 'a U b' '1'
|
||||
|
||||
run 1 ./inf 'a' '1 R a'
|
||||
run 1 ./inf 'a' 'a R 1'
|
||||
run 1 ./inf 'a R b' 'b'
|
||||
run 1 ./inf 'a R b' '1'
|
||||
|
||||
run 1 ./inf 'a U b' '1 U b'
|
||||
run 1 ./inf 'a R b' '1 R b'
|
||||
|
||||
run 1 ./inf 'b * (a U b)' 'a U b'
|
||||
run 1 ./inf 'a U b' 'c + (a U b)'
|
||||
|
||||
exit 0
|
||||
#
|
||||
|
||||
#run 1 ./inf '(a U b) U ((a U b) U (a U b))' 'a U b'
|
||||
#run 1 ./inf '(a U b) && (a U b)' 'a U b'
|
||||
|
||||
'X1' '1'
|
||||
'a U 0' '0'
|
||||
'a R 1' '1'
|
||||
'Xa * Xb' 'X(a * b)'
|
||||
'F(a * GFb)' 'Fa * GFb'
|
||||
'G(a + GFb)' 'Ga + GFb'
|
||||
'X(a * GFb)' 'Xa * GFb'
|
||||
'X(a + GFb)' 'Xa + GFb'
|
||||
150
src/ltltest/reduc.cc
Normal file
150
src/ltltest/reduc.cc
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
// Copyright (C) 2003 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
// 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 <iostream>
|
||||
#include <cassert>
|
||||
#include "ltlparse/public.hh"
|
||||
#include "ltlvisit/lunabbrev.hh"
|
||||
#include "ltlvisit/tunabbrev.hh"
|
||||
#include "ltlvisit/dump.hh"
|
||||
#include "ltlvisit/nenoform.hh"
|
||||
#include "ltlvisit/destroy.hh"
|
||||
#include "ltlvisit/tostring.hh"
|
||||
#include "ltlvisit/reducform.hh"
|
||||
#include "ltlast/allnodes.hh"
|
||||
|
||||
void
|
||||
syntax(char* prog)
|
||||
{
|
||||
std::cerr << prog << " formula1 (formula2)?" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
typedef spot::ltl::formula* ptrfunct(const spot::ltl::formula*);
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
syntax(argv[0]);
|
||||
|
||||
spot::ltl::parse_error_list p1;
|
||||
spot::ltl::formula* f1 = spot::ltl::parse(argv[1], p1);
|
||||
spot::ltl::formula* f2 = NULL;
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[1], p1))
|
||||
return 2;
|
||||
|
||||
|
||||
if (argc == 3){
|
||||
spot::ltl::parse_error_list p2;
|
||||
f2 = spot::ltl::parse(argv[2], p2);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[2], p2))
|
||||
return 2;
|
||||
}
|
||||
|
||||
int exit_code = 0;
|
||||
|
||||
spot::ltl::formula* ftmp1;
|
||||
spot::ltl::formula* ftmp2;
|
||||
|
||||
ftmp1 = f1;
|
||||
f1 = unabbreviate_logic(f1);
|
||||
ftmp2 = f1;
|
||||
f1 = negative_normal_form(f1);
|
||||
spot::ltl::destroy(ftmp1);
|
||||
spot::ltl::destroy(ftmp2);
|
||||
|
||||
|
||||
int length_f1_before = spot::ltl::form_length(f1);
|
||||
std::string f1s_before = spot::ltl::to_string(f1);
|
||||
|
||||
ftmp1 = f1;
|
||||
f1 = spot::ltl::reduce(f1);
|
||||
ftmp2 = f1;
|
||||
f1 = spot::ltl::unabbreviate_logic(f1);
|
||||
spot::ltl::destroy(ftmp1);
|
||||
spot::ltl::destroy(ftmp2);
|
||||
|
||||
int length_f1_after = spot::ltl::form_length(f1);
|
||||
std::string f1s_after = spot::ltl::to_string(f1);
|
||||
|
||||
bool red = (length_f1_after < length_f1_before);
|
||||
if (red);
|
||||
std::string f2s = "";
|
||||
if (f2 != NULL) {
|
||||
ftmp1 = f2;
|
||||
f2 = unabbreviate_logic(f2);
|
||||
ftmp2 = f2;
|
||||
f2 = negative_normal_form(f2);
|
||||
spot::ltl::destroy(ftmp1);
|
||||
spot::ltl::destroy(ftmp2);
|
||||
ftmp1 = f2;
|
||||
f2 = unabbreviate_logic(f2);
|
||||
spot::ltl::destroy(ftmp1);
|
||||
f2s = spot::ltl::to_string(f2);
|
||||
}
|
||||
|
||||
|
||||
if (red && (f2 == NULL)) {
|
||||
std::cout << length_f1_before << " " << length_f1_after
|
||||
<< " '" << f1s_before << "' reduce to '" << f1s_after << "'" << std::endl;
|
||||
}
|
||||
|
||||
if (f2 != NULL){
|
||||
if (f1 != f2) {
|
||||
if (length_f1_after < length_f1_before)
|
||||
std::cout << f1s_before << " ** " << f2s << " ** " << f1s_after << " KOREDUC " << std::endl;
|
||||
else
|
||||
std::cout << f1s_before << " ** " << f2s << " ** " << f1s_after << " KOIDEM " << std::endl;
|
||||
exit_code = 1;
|
||||
}
|
||||
else {
|
||||
if (f1s_before != f1s_after)
|
||||
std::cout << f1s_before << " ** " << f2s << " ** " << f1s_after << " OKREDUC " << std::endl;
|
||||
else
|
||||
std::cout << f1s_before << " ** " << f2s << " ** " << f1s_after << " OKIDEM" << std::endl;
|
||||
exit_code = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (length_f1_after < length_f1_before) exit_code = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
spot::ltl::dump(std::cout, f1); std::cout << std::endl;
|
||||
if (f2 != NULL)
|
||||
spot::ltl::dump(std::cout, f2); std::cout << std::endl;
|
||||
*/
|
||||
|
||||
|
||||
spot::ltl::destroy(f1);
|
||||
if (f2 != NULL)
|
||||
spot::ltl::destroy(f2);
|
||||
|
||||
|
||||
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 exit_code;
|
||||
}
|
||||
134
src/ltltest/reduc.test
Executable file
134
src/ltltest/reduc.test
Executable file
|
|
@ -0,0 +1,134 @@
|
|||
#! /bin/sh
|
||||
# Copyright (C) 2003 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
# département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
# et Marie Curie.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
# Check for the reduc visitor
|
||||
|
||||
#. ./defs || exit 1
|
||||
if [ $1 ]; then
|
||||
FICH=$1
|
||||
else
|
||||
FICH="formules.ltl"
|
||||
fi
|
||||
|
||||
#####################################
|
||||
rm output? result_bri.test -f
|
||||
for opt in bri ##b r i br bi rb ri ib ir bri bir rbi rib ibr irb
|
||||
do
|
||||
for f in `awk '{print $1}' $FICH`
|
||||
do
|
||||
if [ ! $f = "####" ]; then
|
||||
#echo $f;
|
||||
if ./reduc "$f" >> result_$opt.test;
|
||||
then
|
||||
#echo $f >> output1
|
||||
# if ../tgbatest/ltl2tgba -f "$f" >> output1; then #automate FM
|
||||
# echo "" >> output1
|
||||
# else
|
||||
# echo $f;
|
||||
# fi
|
||||
#echo "'$f' is reduce ($NB)"
|
||||
(( NB += 1 ));
|
||||
else
|
||||
(( NB = NB ));
|
||||
#echo "reduc failed to reduce '$f'";
|
||||
fi
|
||||
fi
|
||||
done
|
||||
#echo "$NB formula reduce"
|
||||
(( NB = 0 ));
|
||||
done
|
||||
#####################################
|
||||
|
||||
#ftmp=""
|
||||
#for f in `sed -e "s/\(.* reduce to \)/'1'/" result_bri.test`
|
||||
# do
|
||||
# if [ $ftmp = "" ]; then
|
||||
# echo $ftmp;
|
||||
# ftmp="";
|
||||
# else
|
||||
# echo $f;
|
||||
# ftmp="$ftmp $f";
|
||||
# echo $ftmp;
|
||||
# fi
|
||||
# echo $f >> output2
|
||||
# ../tgbatest/ltl2tgba -f "$f" >> output2 #automate FM
|
||||
# echo "" >> output2
|
||||
#done
|
||||
|
||||
##############################################
|
||||
#exit 0
|
||||
##############################################
|
||||
|
||||
SUM1=0
|
||||
SUM2=0
|
||||
AVG=0
|
||||
for res in `awk '{print $1}' result_bri.test`
|
||||
do
|
||||
SUM1=$(expr $res + $SUM1)
|
||||
done
|
||||
#echo $SUM1
|
||||
|
||||
for res in `awk '{print $2}' result_bri.test`
|
||||
do
|
||||
SUM2=$(expr $res + $SUM2)
|
||||
done
|
||||
(( SUM2 *= 100 ))
|
||||
#echo $SUM2
|
||||
|
||||
if [ ! $SUM1 = 0 ]; then
|
||||
AVG=$(expr $SUM2 / $SUM1)
|
||||
fi
|
||||
|
||||
#AVG=$(expr $AVG / $NB)
|
||||
#AVG=$(expr $AVG)
|
||||
#echo "average reduce $AVG %"
|
||||
|
||||
exit 0;
|
||||
|
||||
### Formule qui ne passe pas !! => Segmentation fault !!
|
||||
#'(((p2)R((X(p2))U(X(1))))*(p0))*((p1)R((p2)R(p0)))'
|
||||
#'(((p2)R((X(p2))U(X(1))))*(p0))'
|
||||
#'((p1)R((p2)R(p0)))'
|
||||
|
||||
#'(p0 R (Gp0 U (p0 U Xp1)))'
|
||||
|
||||
|
||||
#'(((!p)*(X(X(p))))*((p)R((q)+(!q))))+((!q)U(q))'
|
||||
#'X(((p1)R(1))*((0)R((p0)+(p1))))'
|
||||
#'((p0)U(0))U(((0)R(0))*(X(p2)))'
|
||||
#'(((X(1))R(1))U((0)R(1)))R(p0)'
|
||||
#'((X(p0))R(X(p2)))+((0)R((((p2)+(0))*(p0))R(0)))'
|
||||
#'((X(0))+((0)R(p2)))U(((p0)R((p2)*(p2)))R(X(p2)))'
|
||||
#'(p1)R(((p2)R(1))R(((p1)U((1)U(p0)))R((p2)U(0))))'
|
||||
#'(((X(p0))R(X(p0)))R((p0)R(1)))*((0)R((p1)R(0)))'
|
||||
#'(((p1)R(X(p2)))R((0)+((1)U(1))))U((X(1))R(p2))'
|
||||
|
||||
(((!p)*(X(X(p))))*((p)R((q)+(!q))))+((!q)U(q))
|
||||
X(((p1)R(1))*((0)R((p0)+(p1))))
|
||||
((p0)U(0))U(((0)R(0))*(X(p2)))
|
||||
(((X(1))R(1))U((0)R(1)))R(p0)
|
||||
((X(p0))R(X(p2)))+((0)R((((p2)+(0))*(p0))R(0)))
|
||||
((X(0))+((0)R(p2)))U(((p0)R((p2)*(p2)))R(X(p2)))
|
||||
(p1)R(((p2)R(1))R(((p1)U((1)U(p0)))R((p2)U(0))))
|
||||
(((X(p0))R(X(p0)))R((p0)R(1)))*((0)R((p1)R(0)))
|
||||
(((p1)R(X(p2)))R((0)+((1)U(1))))U((X(1))R(p2))
|
||||
|
|
@ -33,7 +33,8 @@ ltlvisit_HEADERS = \
|
|||
lunabbrev.hh \
|
||||
nenoform.hh \
|
||||
postfix.hh \
|
||||
tunabbrev.hh
|
||||
tunabbrev.hh \
|
||||
reducform.hh
|
||||
|
||||
noinst_LTLIBRARIES = libltlvisit.la
|
||||
libltlvisit_la_SOURCES = \
|
||||
|
|
@ -45,4 +46,8 @@ libltlvisit_la_SOURCES = \
|
|||
lunabbrev.cc \
|
||||
nenoform.cc \
|
||||
postfix.cc \
|
||||
tunabbrev.cc
|
||||
tunabbrev.cc \
|
||||
reducform.cc \
|
||||
basereduc.cc \
|
||||
forminf.cc \
|
||||
formlength.cc
|
||||
578
src/ltlvisit/basereduc.cc
Normal file
578
src/ltlvisit/basereduc.cc
Normal file
|
|
@ -0,0 +1,578 @@
|
|||
// Copyright (C) 2003 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
// 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 "reducform.hh"
|
||||
#include "ltlast/allnodes.hh"
|
||||
#include "ltlvisit/clone.hh"
|
||||
#include <cassert>
|
||||
|
||||
#include "ltlvisit/destroy.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
class basic_reduce_form_visitor : public visitor
|
||||
{
|
||||
public:
|
||||
|
||||
basic_reduce_form_visitor(){}
|
||||
|
||||
virtual ~basic_reduce_form_visitor(){}
|
||||
|
||||
formula*
|
||||
result() const
|
||||
{
|
||||
return result_;
|
||||
}
|
||||
|
||||
void
|
||||
visit(atomic_prop* ap)
|
||||
{
|
||||
formula* f = ap->ref();
|
||||
result_ = f;
|
||||
}
|
||||
|
||||
void
|
||||
visit(constant* c)
|
||||
{
|
||||
switch (c->val())
|
||||
{
|
||||
case constant::True:
|
||||
result_ = constant::true_instance();
|
||||
return;
|
||||
case constant::False:
|
||||
result_ = constant::false_instance();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
visit(unop* uo)
|
||||
{
|
||||
formula* f = uo->child();
|
||||
result_ = basic_reduce_form(f);
|
||||
switch (uo->op())
|
||||
{
|
||||
case unop::Not:
|
||||
result_ = unop::instance(unop::Not, result_);
|
||||
return;
|
||||
|
||||
case unop::X:
|
||||
/* X(true) = true
|
||||
X(false) = false */
|
||||
if (node_type(result_) == (node_type_form_visitor::Const))
|
||||
return;
|
||||
|
||||
/* XGF(f) = GF(f) */
|
||||
if (is_GF(result_)) return;
|
||||
|
||||
/* X(f1 & GF(f2)) = X(f1) & GF(F2) */
|
||||
/* X(f1 | GF(f2)) = X(f1) | GF(F2) */
|
||||
if (node_type(result_) == (node_type_form_visitor::Multop)) {
|
||||
if (spot::ltl::nb_term_multop(result_) == 2) {
|
||||
if (is_GF(((multop*)result_)->nth(0)) ||
|
||||
is_FG(((multop*)result_)->nth(0))) {
|
||||
multop::vec* res = new multop::vec;
|
||||
res->push_back(unop::instance(unop::F, basic_reduce_form(((multop*)result_)->nth(1))));
|
||||
res->push_back(basic_reduce_form(((multop*)result_)->nth(0)));
|
||||
f = result_;
|
||||
result_ = multop::instance(((multop*)(result_))->op(), res);
|
||||
spot::ltl::destroy(f);
|
||||
return;
|
||||
}
|
||||
if (is_GF(((multop*)result_)->nth(1)) ||
|
||||
is_FG(((multop*)result_)->nth(1))) {
|
||||
multop::vec* res = new multop::vec;
|
||||
res->push_back(unop::instance(unop::F, basic_reduce_form(((multop*)result_)->nth(0))));
|
||||
res->push_back(basic_reduce_form(((multop*)result_)->nth(1)));
|
||||
f = result_;
|
||||
result_ = multop::instance(((multop*)(result_))->op(), res);
|
||||
spot::ltl::destroy(f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result_ = unop::instance(unop::X, result_);
|
||||
return;
|
||||
|
||||
case unop::F:
|
||||
|
||||
/* F(true) = true
|
||||
F(false) = false */
|
||||
if (node_type(result_) == (node_type_form_visitor::Const))
|
||||
return;
|
||||
|
||||
/* FX(a) = XF(a) */
|
||||
if (node_type(result_) == (node_type_form_visitor::Unop))
|
||||
if ( ((unop*)(result_))->op() == unop::X ){
|
||||
f = result_;
|
||||
result_ = unop::instance(unop::X,
|
||||
unop::instance(unop::F,
|
||||
basic_reduce_form(((unop*)(result_))->child()) ));
|
||||
spot::ltl::destroy(f);
|
||||
return;
|
||||
}
|
||||
|
||||
/* F(f1 & GF(f2)) = F(f1) & GF(F2) */
|
||||
if (node_type(result_) == (node_type_form_visitor::Multop)) {
|
||||
if ( ((multop*)(result_))->op() == multop::And ) {
|
||||
if (spot::ltl::nb_term_multop(result_) == 2) {
|
||||
if (is_GF(((multop*)result_)->nth(0)) ||
|
||||
is_FG(((multop*)result_)->nth(0))) {
|
||||
multop::vec* res = new multop::vec;
|
||||
res->push_back(unop::instance(unop::F, basic_reduce_form(((multop*)result_)->nth(1))));
|
||||
res->push_back(basic_reduce_form(((multop*)result_)->nth(0)));
|
||||
spot::ltl::destroy(result_);
|
||||
result_ = multop::instance(multop::And, res);
|
||||
return;
|
||||
}
|
||||
if (is_GF(((multop*)result_)->nth(1)) ||
|
||||
is_FG(((multop*)result_)->nth(1))) {
|
||||
multop::vec* res = new multop::vec;
|
||||
res->push_back(unop::instance(unop::F, basic_reduce_form(((multop*)result_)->nth(0))));
|
||||
res->push_back(basic_reduce_form(((multop*)result_)->nth(1)));
|
||||
spot::ltl::destroy(result_);
|
||||
result_ = multop::instance(multop::And, res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result_ = unop::instance(unop::F, result_);
|
||||
return;
|
||||
|
||||
case unop::G:
|
||||
|
||||
/* G(true) = true
|
||||
G(false) = false */
|
||||
if (node_type(result_) == (node_type_form_visitor::Const))
|
||||
return;
|
||||
|
||||
/* G(a R b) = G(b) */
|
||||
if (node_type(result_) == node_type_form_visitor::Binop)
|
||||
if ( ((binop*)(result_))->op() == binop::R ){
|
||||
f = result_;
|
||||
result_ = unop::instance(unop::G, basic_reduce_form(((binop*)(result_))->second()));
|
||||
spot::ltl::destroy(f);
|
||||
return;
|
||||
}
|
||||
|
||||
/* GX(a) = XG(a) */
|
||||
if (node_type(result_) == (node_type_form_visitor::Unop))
|
||||
if ( ((unop*)(result_))->op() == unop::X ){
|
||||
f = result_;
|
||||
result_ = unop::instance(unop::X,
|
||||
unop::instance(unop::G,
|
||||
basic_reduce_form(((unop*)(result_))->child()) ));
|
||||
spot::ltl::destroy(f);
|
||||
return;
|
||||
}
|
||||
|
||||
/* G(f1 | GF(f2)) = G(f1) | GF(F2) */
|
||||
if (node_type(result_) == (node_type_form_visitor::Multop)) {
|
||||
if ( ((multop*)(f))->op() == multop::Or ) {
|
||||
if (spot::ltl::nb_term_multop(result_) == 2) {
|
||||
if (is_GF(((multop*)result_)->nth(0)) ||
|
||||
is_FG(((multop*)result_)->nth(0))) {
|
||||
multop::vec* res = new multop::vec;
|
||||
res->push_back(unop::instance(unop::G, basic_reduce_form(((multop*)result_)->nth(1))));
|
||||
res->push_back(basic_reduce_form(((multop*)result_)->nth(0)));
|
||||
spot::ltl::destroy(result_);
|
||||
result_ = multop::instance(multop::Or, res);
|
||||
return;
|
||||
}
|
||||
if (is_GF(((multop*)result_)->nth(1)) ||
|
||||
is_FG(((multop*)result_)->nth(1))) {
|
||||
multop::vec* res = new multop::vec;
|
||||
res->push_back(unop::instance(unop::G, basic_reduce_form(((multop*)result_)->nth(0))));
|
||||
res->push_back(basic_reduce_form(((multop*)result_)->nth(1)));
|
||||
spot::ltl::destroy(result_);
|
||||
result_ = multop::instance(multop::Or, res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result_ = unop::instance(unop::G, result_);
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(binop* bo)
|
||||
{
|
||||
formula* f1 = bo->first();
|
||||
formula* f2 = bo->second();
|
||||
formula* ftmp = NULL;
|
||||
node_type_form_visitor v1;
|
||||
node_type_form_visitor v2;
|
||||
switch (bo->op())
|
||||
{
|
||||
case binop::Xor:
|
||||
result_ = binop::instance(binop::Xor,
|
||||
basic_reduce_form(f1),
|
||||
basic_reduce_form(f2));
|
||||
return;
|
||||
case binop::Equiv:
|
||||
result_ = binop::instance(binop::Equiv,
|
||||
basic_reduce_form(f1),
|
||||
basic_reduce_form(f2));
|
||||
return;
|
||||
case binop::Implies:
|
||||
result_ = binop::instance(binop::Implies,
|
||||
basic_reduce_form(f1),
|
||||
basic_reduce_form(f2));
|
||||
return;
|
||||
case binop::U:
|
||||
f2 = basic_reduce_form(f2);
|
||||
|
||||
/* a U false = false
|
||||
a U true = true */
|
||||
if (node_type(f2) == (node_type_form_visitor::Const)) {
|
||||
result_ = f2;
|
||||
return;
|
||||
}
|
||||
|
||||
f1 = basic_reduce_form(f1);
|
||||
|
||||
/* X(a) U X(b) = X(a U b) */
|
||||
if ( node_type(f1) == (node_type_form_visitor::Unop)
|
||||
&& node_type(f2) == (node_type_form_visitor::Unop)) {
|
||||
if ( (((unop*)(f1))->op() == unop::X)
|
||||
&& (((unop*)(f2))->op() == unop::X) ) {
|
||||
ftmp = binop::instance(binop::U,
|
||||
basic_reduce_form(((unop*)(f1))->child()),
|
||||
basic_reduce_form(((unop*)(f2))->child()));
|
||||
result_ = unop::instance(unop::X, basic_reduce_form(ftmp));
|
||||
spot::ltl::destroy(f1);
|
||||
spot::ltl::destroy(f2);
|
||||
spot::ltl::destroy(ftmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
result_ = binop::instance(binop::U, f1, f2);
|
||||
return;
|
||||
|
||||
case binop::R:
|
||||
f2 = basic_reduce_form(f2);
|
||||
|
||||
/* a R false = false
|
||||
a R true = true */
|
||||
if (node_type(f2) == (node_type_form_visitor::Const)) {
|
||||
result_ = f2;
|
||||
return;
|
||||
}
|
||||
|
||||
f1 = basic_reduce_form(f1);
|
||||
|
||||
/* X(a) R X(b) = X(a R b) */
|
||||
if ( node_type(f1) == (node_type_form_visitor::Unop)
|
||||
&& node_type(f2) == (node_type_form_visitor::Unop)) {
|
||||
if ( (((unop*)(f1))->op() == unop::X)
|
||||
&& (((unop*)(f2))->op() == unop::X) ) {
|
||||
ftmp = binop::instance(bo->op(),
|
||||
basic_reduce_form(((unop*)(f1))->child()),
|
||||
basic_reduce_form(((unop*)(f2))->child()));
|
||||
result_ = unop::instance(unop::X, basic_reduce_form(ftmp));
|
||||
spot::ltl::destroy(f1);
|
||||
spot::ltl::destroy(f2);
|
||||
spot::ltl::destroy(ftmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
result_ = binop::instance(bo->op(),
|
||||
f1, f2);
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(multop* mo)
|
||||
{
|
||||
if (mo == NULL);
|
||||
multop::type op = mo->op();
|
||||
unsigned mos = mo->size();
|
||||
multop::vec* res = new multop::vec;
|
||||
|
||||
multop::vec* tmpX = new multop::vec;
|
||||
multop::vec* tmpU = new multop::vec;
|
||||
multop::vec* tmpUright = NULL;
|
||||
multop::vec* tmpR = new multop::vec;
|
||||
multop::vec* tmpRright = NULL;
|
||||
multop::vec* tmpFG = new multop::vec;
|
||||
multop::vec* tmpGF = new multop::vec;
|
||||
|
||||
multop::vec* tmpOther = new multop::vec;
|
||||
|
||||
formula* ftmp = NULL;
|
||||
|
||||
for (unsigned i = 0; i < mos; ++i)
|
||||
res->push_back(basic_reduce_form(mo->nth(i)));
|
||||
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case multop::And:
|
||||
|
||||
for (multop::vec::iterator i = res->begin(); i != res->end(); i++) {
|
||||
if (*i == NULL) continue;
|
||||
switch (node_type(*i)) {
|
||||
|
||||
case node_type_form_visitor::Unop:
|
||||
|
||||
/* Xa & Xb = X(a & b)*/
|
||||
if (((unop*)(*i))->op() == unop::X) {
|
||||
tmpX->push_back( spot::ltl::basic_reduce_form(((unop*)(*i))->child()) );
|
||||
break;
|
||||
}
|
||||
|
||||
/* FG(a) & FG(b) = FG(a & b)*/
|
||||
if (is_FG(*i)) {
|
||||
tmpFG->push_back( spot::ltl::basic_reduce_form( ((unop*)((unop*)(*i))->child())->child() ) );
|
||||
break;
|
||||
}
|
||||
tmpOther->push_back(spot::ltl::basic_reduce_form(*i));
|
||||
break;
|
||||
/* A GERER !!!!!!!!!!!!!!!!!!!!!!!
|
||||
case node_type_form_visitor::Const:
|
||||
tmpX->push_back( spot::ltl::clone((*i)) );
|
||||
break;
|
||||
*/
|
||||
|
||||
case node_type_form_visitor::Binop:
|
||||
|
||||
/* (a U b) & (c U b) = (a & c) U b */
|
||||
if (((binop*)(*i))->op() == binop::U) {
|
||||
ftmp = ((binop*)(*i))->second();
|
||||
tmpUright = new multop::vec;
|
||||
for (multop::vec::iterator j = i; j != res->end(); j++)
|
||||
{
|
||||
if (*j == NULL) continue;
|
||||
if (node_type(*j) == node_type_form_visitor::Binop)
|
||||
{
|
||||
if (((binop*)(*j))->op() == binop::U)
|
||||
{
|
||||
if (ftmp == ((binop*)(*j))->second())
|
||||
{
|
||||
tmpUright->push_back(spot::ltl::basic_reduce_form(((binop*)(*j))->first() ));
|
||||
if (j != i) {
|
||||
spot::ltl::destroy(*j);
|
||||
*j = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tmpU->push_back(binop::instance(binop::U,
|
||||
multop::instance(multop::And,tmpUright),
|
||||
basic_reduce_form(ftmp)));
|
||||
break;
|
||||
}
|
||||
|
||||
/* (a R b) & (a R c) = a R (b & c) */
|
||||
if (((binop*)(*i))->op() == binop::R) {
|
||||
ftmp = ((binop*)(*i))->first();
|
||||
tmpRright = new multop::vec;
|
||||
for (multop::vec::iterator j = i; j != res->end(); j++)
|
||||
{
|
||||
if (*j == NULL) continue;
|
||||
if (node_type(*j) == node_type_form_visitor::Binop)
|
||||
{
|
||||
if (((binop*)(*j))->op() == binop::R)
|
||||
{
|
||||
if (ftmp == ((binop*)(*j))->first())
|
||||
{
|
||||
tmpRright->push_back(spot::ltl::basic_reduce_form(((binop*)(*j))->second() ));
|
||||
if (j != i) {
|
||||
spot::ltl::destroy(*j);
|
||||
*j = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tmpR->push_back(binop::instance(binop::R,
|
||||
basic_reduce_form(ftmp),
|
||||
multop::instance(multop::And,tmpRright)));
|
||||
break;
|
||||
}
|
||||
tmpOther->push_back(spot::ltl::basic_reduce_form(*i));
|
||||
break;
|
||||
default:
|
||||
tmpOther->push_back(spot::ltl::basic_reduce_form(*i));
|
||||
break;
|
||||
}
|
||||
spot::ltl::destroy(*i);
|
||||
}
|
||||
|
||||
delete(tmpGF);
|
||||
tmpGF = NULL;
|
||||
|
||||
break;
|
||||
|
||||
case multop::Or:
|
||||
|
||||
for (multop::vec::iterator i = res->begin(); i != res->end(); i++) {
|
||||
if (*i == NULL) continue;
|
||||
switch (node_type(*i)) {
|
||||
|
||||
case node_type_form_visitor::Unop:
|
||||
|
||||
/* Xa | Xb = X(a | b)*/
|
||||
if (((unop*)(*i))->op() == unop::X) {
|
||||
tmpX->push_back( spot::ltl::basic_reduce_form(((unop*)(*i))->child()) );
|
||||
break;
|
||||
}
|
||||
|
||||
/* GF(a) & GF(b) = GF(a & b)*/
|
||||
if (is_GF(*i)) {
|
||||
tmpGF->push_back( spot::ltl::basic_reduce_form( ((unop*)((unop*)(*i))->child())->child() ) );
|
||||
break;
|
||||
}
|
||||
tmpOther->push_back(spot::ltl::basic_reduce_form(*i));
|
||||
break;
|
||||
|
||||
case node_type_form_visitor::Binop:
|
||||
|
||||
/* (a U b) | (a U c) = a U (b | c) */
|
||||
if (((binop*)(*i))->op() == binop::U) {
|
||||
ftmp = ((binop*)(*i))->first();
|
||||
tmpUright = new multop::vec;
|
||||
for (multop::vec::iterator j = i; j != res->end(); j++)
|
||||
{
|
||||
if (*j == NULL) continue;
|
||||
if (node_type(*j) == node_type_form_visitor::Binop)
|
||||
{
|
||||
if (((binop*)(*j))->op() == binop::U)
|
||||
{
|
||||
if (ftmp == ((binop*)(*j))->first())
|
||||
{
|
||||
tmpUright->push_back(spot::ltl::basic_reduce_form(((binop*)(*j))->second() ));
|
||||
if (j != i) {
|
||||
spot::ltl::destroy(*j);
|
||||
*j = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tmpU->push_back(binop::instance(binop::U,
|
||||
basic_reduce_form(ftmp),
|
||||
multop::instance(multop::Or,tmpUright)));
|
||||
break;
|
||||
}
|
||||
|
||||
/* (a R b) | (c R b) = (a | c) R b */
|
||||
if (((binop*)(*i))->op() == binop::R) {
|
||||
ftmp = ((binop*)(*i))->second();
|
||||
tmpRright = new multop::vec;
|
||||
for (multop::vec::iterator j = i; j != res->end(); j++)
|
||||
{
|
||||
if (*j == NULL) continue;
|
||||
if (node_type(*j) == node_type_form_visitor::Binop)
|
||||
{
|
||||
if (((binop*)(*j))->op() == binop::R)
|
||||
{
|
||||
if (ftmp == ((binop*)(*j))->second())
|
||||
{
|
||||
tmpRright->push_back(spot::ltl::basic_reduce_form(((binop*)(*j))->first() ));
|
||||
if (j != i) {
|
||||
spot::ltl::destroy(*j);
|
||||
*j = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tmpR->push_back(binop::instance(binop::R,
|
||||
multop::instance(multop::Or,tmpRright),
|
||||
basic_reduce_form(ftmp)));
|
||||
break;
|
||||
}
|
||||
tmpOther->push_back(spot::ltl::basic_reduce_form(*i));
|
||||
break;
|
||||
default:
|
||||
tmpOther->push_back(spot::ltl::basic_reduce_form(*i));
|
||||
break;
|
||||
}
|
||||
spot::ltl::destroy(*i);
|
||||
}
|
||||
|
||||
delete(tmpFG);
|
||||
tmpFG = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
res->clear();
|
||||
delete(res);
|
||||
|
||||
if (tmpX->size())
|
||||
tmpOther->push_back(unop::instance(unop::X,multop::instance(mo->op(),tmpX)));
|
||||
else delete(tmpX);
|
||||
|
||||
if (tmpU->size())
|
||||
tmpOther->push_back(multop::instance(mo->op(),tmpU));
|
||||
else delete(tmpU);
|
||||
|
||||
if (tmpR->size())
|
||||
tmpOther->push_back(multop::instance(mo->op(),tmpR));
|
||||
else delete(tmpR);
|
||||
|
||||
if (tmpGF != NULL)
|
||||
if (tmpGF->size())
|
||||
tmpOther->push_back(unop::instance(unop::G,
|
||||
unop::instance(unop::F,
|
||||
multop::instance(mo->op(),tmpGF))));
|
||||
if (tmpFG != NULL)
|
||||
if (tmpFG->size())
|
||||
tmpOther->push_back(unop::instance(unop::G,
|
||||
unop::instance(unop::F,
|
||||
multop::instance(mo->op(),tmpFG))));
|
||||
|
||||
result_ = multop::instance(op, tmpOther);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
formula* result_;
|
||||
};
|
||||
|
||||
formula* basic_reduce_form(const formula* f)
|
||||
{
|
||||
basic_reduce_form_visitor v;
|
||||
const_cast<formula*>(f)->accept(v);
|
||||
return v.result();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
619
src/ltlvisit/forminf.cc
Normal file
619
src/ltlvisit/forminf.cc
Normal file
|
|
@ -0,0 +1,619 @@
|
|||
// Copyright (C) 2003 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
// 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 "reducform.hh"
|
||||
#include "ltlast/allnodes.hh"
|
||||
#include <cassert>
|
||||
|
||||
#include "lunabbrev.hh"
|
||||
#include "nenoform.hh"
|
||||
#include "ltlvisit/destroy.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
|
||||
bool
|
||||
is_GF(const formula* f)
|
||||
{
|
||||
if ((const unop*)f != NULL)
|
||||
if (((const unop*)f)->op() == unop::G)
|
||||
if ((const unop*)(((const unop*)f)->child()) != NULL)
|
||||
if (((const unop*)((const unop*)f)->child())->op() == unop::F)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
is_FG(const formula* f)
|
||||
{
|
||||
if ((const unop*)f != NULL)
|
||||
if (((const unop*)f)->op() == unop::F)
|
||||
if ((const unop*)(((const unop*)f)->child()) != NULL)
|
||||
if (((const unop*)((const unop*)f)->child())->op() == unop::G)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
nb_term_multop(const formula* f)
|
||||
{
|
||||
if ((const multop*)f == NULL) return -1;
|
||||
|
||||
unsigned mos = ((const multop*)(f))->size();
|
||||
return mos;
|
||||
}
|
||||
|
||||
|
||||
node_type_form_visitor::node_type_form_visitor(){}
|
||||
|
||||
node_type_form_visitor::type
|
||||
node_type_form_visitor::result() const { return result_;}
|
||||
|
||||
void
|
||||
node_type_form_visitor::visit(const atomic_prop* ap){
|
||||
if (ap == NULL);
|
||||
result_ = node_type_form_visitor::Atom;
|
||||
}
|
||||
|
||||
void
|
||||
node_type_form_visitor::visit(const constant* c){
|
||||
if (c == NULL);
|
||||
result_ = node_type_form_visitor::Const;
|
||||
}
|
||||
|
||||
void
|
||||
node_type_form_visitor::visit(const unop* uo){
|
||||
if (uo == NULL);
|
||||
result_ = node_type_form_visitor::Unop;
|
||||
}
|
||||
|
||||
void
|
||||
node_type_form_visitor::visit(const binop* bo){
|
||||
if (bo == NULL);
|
||||
result_ = node_type_form_visitor::Binop;
|
||||
}
|
||||
|
||||
void
|
||||
node_type_form_visitor::visit(const multop* mo){
|
||||
if (mo == NULL);
|
||||
result_ = node_type_form_visitor::Multop;
|
||||
}
|
||||
|
||||
node_type_form_visitor::type node_type(const formula* f)
|
||||
{
|
||||
node_type_form_visitor v;
|
||||
if (f == NULL) std::cout << "f == NULL !!!!!!!!" << std::endl;
|
||||
const_cast<formula*>(f)->accept(v);
|
||||
return v.result();
|
||||
}
|
||||
|
||||
class form_eventual_universal_visitor : public const_visitor
|
||||
{
|
||||
public:
|
||||
|
||||
form_eventual_universal_visitor()
|
||||
{
|
||||
eventual = false; // faux au départ
|
||||
universal = false;
|
||||
}
|
||||
|
||||
virtual ~form_eventual_universal_visitor()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
is_eventual() const
|
||||
{
|
||||
return eventual;
|
||||
}
|
||||
|
||||
bool
|
||||
is_universal() const
|
||||
{
|
||||
return universal;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const atomic_prop* ap)
|
||||
{
|
||||
if (ap);
|
||||
}
|
||||
|
||||
void
|
||||
visit(const constant* c)
|
||||
{
|
||||
if (c->val());
|
||||
}
|
||||
|
||||
void
|
||||
visit(const unop* uo)
|
||||
{
|
||||
const formula* f1 = uo->child();
|
||||
switch (uo->op())
|
||||
{
|
||||
case unop::Not:
|
||||
case unop::X:
|
||||
eventual = recurse_ev(f1);
|
||||
universal = recurse_un(f1);
|
||||
return;
|
||||
case unop::F:
|
||||
eventual = true;
|
||||
return;
|
||||
case unop::G:
|
||||
universal = true;
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(const binop* bo)
|
||||
{
|
||||
const formula* f1 = bo->first();
|
||||
switch (bo->op())
|
||||
{
|
||||
case binop::Xor:
|
||||
case binop::Equiv:
|
||||
case binop::Implies:
|
||||
return;
|
||||
case binop::U:
|
||||
if (node_type(f1) == node_type_form_visitor::Const)
|
||||
if (((const constant*)f1)->val() == constant::True)
|
||||
eventual = true;
|
||||
return;
|
||||
case binop::R:
|
||||
if (node_type(f1) != node_type_form_visitor::Const)
|
||||
if (((const constant*)f1)->val() == constant::False)
|
||||
universal = true;
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(const multop* mo)
|
||||
{
|
||||
if (mo == NULL);
|
||||
unsigned mos = mo->size();
|
||||
|
||||
eventual = true;
|
||||
universal = true;
|
||||
for (unsigned i = 0; i < mos; ++i){
|
||||
if ( !(recurse_ev(mo->nth(i))) ){
|
||||
eventual = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < mos; ++i){
|
||||
if ( !(recurse_un(mo->nth(i))) ){
|
||||
universal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
recurse_ev(const formula* f)
|
||||
{
|
||||
form_eventual_universal_visitor v;
|
||||
const_cast<formula*>(f)->accept(v);
|
||||
return v.is_eventual();
|
||||
}
|
||||
|
||||
bool
|
||||
recurse_un(const formula* f)
|
||||
{
|
||||
form_eventual_universal_visitor v;
|
||||
const_cast<formula*>(f)->accept(v);
|
||||
return v.is_universal();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool eventual;
|
||||
bool universal;
|
||||
};
|
||||
|
||||
|
||||
bool is_eventual(const formula* f)
|
||||
{
|
||||
form_eventual_universal_visitor v;
|
||||
const_cast<formula*>(f)->accept(v);
|
||||
return v.is_eventual();
|
||||
}
|
||||
|
||||
bool is_universal(const formula* f)
|
||||
{
|
||||
form_eventual_universal_visitor v;
|
||||
const_cast<formula*>(f)->accept(v);
|
||||
return v.is_universal();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class inf_form_right_recurse_visitor : public const_visitor
|
||||
{
|
||||
public:
|
||||
|
||||
inf_form_right_recurse_visitor(const formula *f)
|
||||
{
|
||||
this->f = f;
|
||||
result_ = false; // faux au départ
|
||||
}
|
||||
|
||||
virtual ~inf_form_right_recurse_visitor()
|
||||
{
|
||||
}
|
||||
/*
|
||||
bool special_case(const formula* f2,binop::operator op)
|
||||
{
|
||||
const binop* b = (const binop*)f;
|
||||
const binop* b2 = (const binop*)f2;
|
||||
if ((b != NULL) && (b2 != NULL) &&
|
||||
(b->op() == b2_>op() == op))
|
||||
if (inf_form(b2->first(),b->first())
|
||||
&& inf_form(b2->second(),b->second()) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
int
|
||||
result() const
|
||||
{
|
||||
return result_;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const atomic_prop* ap)
|
||||
{
|
||||
if ((const atomic_prop*)f == ap)
|
||||
result_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const constant* c)
|
||||
{
|
||||
switch (c->val())
|
||||
{
|
||||
case constant::True:
|
||||
result_ = true;
|
||||
return;
|
||||
case constant::False:
|
||||
result_ = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
visit(const unop* uo)
|
||||
{
|
||||
const formula* f1 = uo->child();
|
||||
const formula* tmp = NULL;
|
||||
switch (uo->op())
|
||||
{
|
||||
case unop::Not:// à gérer !!
|
||||
return;
|
||||
case unop::X:// à gérer !!
|
||||
return;
|
||||
case unop::F:
|
||||
// F(a) = true U a
|
||||
result_ = inf_form(f,f1);
|
||||
return;
|
||||
case unop::G:
|
||||
// G(a) = false R a
|
||||
tmp = constant::false_instance();
|
||||
if ( inf_form(f,tmp) )
|
||||
result_ = true;
|
||||
spot::ltl::destroy(tmp);
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(const binop* bo)
|
||||
{
|
||||
const formula* f1 = bo->first();
|
||||
const formula* f2 = bo->second();
|
||||
switch (bo->op())
|
||||
{
|
||||
case binop::Xor:
|
||||
case binop::Equiv:
|
||||
case binop::Implies:
|
||||
return;
|
||||
case binop::U:
|
||||
if ( (inf_form(f,f2)) )
|
||||
result_ = true;
|
||||
return;
|
||||
case binop::R:
|
||||
if ( (inf_form(f,f1)) && (inf_form(f,f2)) )
|
||||
result_ = true;
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(const multop* mo)
|
||||
{
|
||||
if (mo == NULL);
|
||||
multop::type op = mo->op();
|
||||
unsigned mos = mo->size();
|
||||
switch (op)
|
||||
{
|
||||
case multop::And:
|
||||
for (unsigned i = 0; (i < mos) ; ++i)
|
||||
if ( !(inf_form(f,mo->nth(i))) )
|
||||
return;
|
||||
result_ = true;
|
||||
break;
|
||||
case multop::Or:
|
||||
for (unsigned i = 0; i < mos && !result_; ++i)
|
||||
if ( (inf_form(f,mo->nth(i))) )
|
||||
result_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
recurse(const formula* f1, const formula* f2)
|
||||
{
|
||||
if (f1 == f2) return true;
|
||||
inf_form_right_recurse_visitor v(f2);
|
||||
const_cast<formula*>(f1)->accept(v);
|
||||
return v.result();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool result_; // true si f < f1, false sinon.
|
||||
const formula* f;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class inf_form_left_recurse_visitor : public const_visitor
|
||||
{
|
||||
public:
|
||||
|
||||
inf_form_left_recurse_visitor(const formula *f)
|
||||
{
|
||||
this->f = f;
|
||||
result_ = false;
|
||||
}
|
||||
|
||||
virtual ~inf_form_left_recurse_visitor()
|
||||
{
|
||||
}
|
||||
|
||||
bool special_case(const formula* f2)
|
||||
{
|
||||
if ((node_type(f) == node_type_form_visitor::Binop)
|
||||
&& (node_type(f2) == node_type_form_visitor::Binop))
|
||||
if (((const binop*)f)->op() == ((const binop*)f2)->op())
|
||||
if (inf_form(((const binop*)f2)->first(),((const binop*)f)->first())
|
||||
&& inf_form(((const binop*)f2)->second(),((const binop*)f)->second()) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
result() const
|
||||
{
|
||||
return result_;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const atomic_prop* ap)
|
||||
{
|
||||
inf_form_right_recurse_visitor v(ap);
|
||||
const_cast<formula*>(f)->accept(v);
|
||||
result_ = v.result();
|
||||
}
|
||||
|
||||
void
|
||||
visit(const constant* c)
|
||||
{
|
||||
inf_form_right_recurse_visitor v(c);
|
||||
switch (c->val())
|
||||
{
|
||||
case constant::True:
|
||||
const_cast<formula*>(f)->accept(v);
|
||||
result_ = v.result();
|
||||
return;
|
||||
case constant::False:
|
||||
result_ = true;
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(const unop* uo)
|
||||
{
|
||||
const formula* f1 = uo->child();
|
||||
const formula* tmp = NULL;
|
||||
inf_form_right_recurse_visitor v(uo);
|
||||
switch (uo->op())
|
||||
{
|
||||
case unop::Not:
|
||||
if (uo == f)
|
||||
result_ = true;
|
||||
return;
|
||||
case unop::X:
|
||||
if (node_type(f) == node_type_form_visitor::Unop)
|
||||
if (((const unop*)f)->op() == unop::X) {
|
||||
result_ = inf_form(f1,((const unop*)f)->child());
|
||||
}
|
||||
return;
|
||||
case unop::F:
|
||||
// F(a) = true U a
|
||||
tmp = binop::instance(binop::U,constant::true_instance(),clone(f1));
|
||||
if (this->special_case(tmp)){
|
||||
result_ = true;
|
||||
spot::ltl::destroy(tmp);
|
||||
return;
|
||||
}
|
||||
if ( inf_form(tmp,f) )
|
||||
result_ = true;
|
||||
spot::ltl::destroy(tmp);
|
||||
return;
|
||||
case unop::G:
|
||||
// F(a) = false R a
|
||||
tmp = binop::instance(binop::R,constant::false_instance(),clone(f1));
|
||||
if (this->special_case(tmp)){
|
||||
result_ = true;
|
||||
spot::ltl::destroy(tmp);
|
||||
return;
|
||||
}
|
||||
if ( inf_form(f1,f) )
|
||||
result_ = true;
|
||||
spot::ltl::destroy(tmp);
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(const binop* bo)
|
||||
{
|
||||
|
||||
if (this->special_case(bo))
|
||||
{
|
||||
result_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const formula* f1 = bo->first();
|
||||
const formula* f2 = bo->second();
|
||||
switch (bo->op())
|
||||
{
|
||||
case binop::Xor:
|
||||
case binop::Equiv:
|
||||
case binop::Implies:
|
||||
return;
|
||||
case binop::U:
|
||||
if ( (inf_form(f1,f)) && (inf_form(f2,f)) )
|
||||
result_ = true;
|
||||
return;
|
||||
case binop::R:
|
||||
if ( (inf_form(f2,f)) )
|
||||
result_ = true;
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(const multop* mo)
|
||||
{
|
||||
if (mo == NULL);
|
||||
multop::type op = mo->op();
|
||||
unsigned mos = mo->size();
|
||||
switch (op)
|
||||
{
|
||||
case multop::And:
|
||||
for (unsigned i = 0; (i < mos) && !result_ ; ++i)
|
||||
if ( (inf_form(mo->nth(i),f)) )
|
||||
result_ = true;
|
||||
break;
|
||||
case multop::Or:
|
||||
for (unsigned i = 0; i < mos ; ++i)
|
||||
if ( !(inf_form(mo->nth(i),f)) )
|
||||
return;
|
||||
result_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
bool result_; // true if f1 < f, 1 otherwise.
|
||||
const formula* f;
|
||||
};
|
||||
|
||||
bool inf_form(const formula* f1, const formula* f2)
|
||||
{
|
||||
// f1 and f2 are unabbreviate
|
||||
if (f1 == f2) return true;
|
||||
inf_form_left_recurse_visitor v1(f2);
|
||||
inf_form_right_recurse_visitor v2(f1);
|
||||
|
||||
if ( (node_type(f1) == node_type_form_visitor::Const) &&
|
||||
(node_type(f2) == node_type_form_visitor::Const) )
|
||||
if ( (((const constant*)f2)->val() == constant::True) ||
|
||||
(((const constant*)f1)->val() == constant::False) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const_cast<formula*>(f1)->accept(v1);
|
||||
if (v1.result()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const_cast<formula*>(f2)->accept(v2);
|
||||
if (v2.result()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool infneg_form(const formula* f1, const formula* f2, int n)
|
||||
{
|
||||
const formula* ftmp1;
|
||||
const formula* ftmp2;
|
||||
const formula* ftmp3 = unop::instance(unop::Not,(n == 0)? clone(f1) : clone(f2));
|
||||
const formula* ftmp4 = spot::ltl::negative_normal_form((n == 0)? f2 : f1);
|
||||
const formula* ftmp5;
|
||||
const formula* ftmp6;
|
||||
bool retour;
|
||||
|
||||
ftmp2 = spot::ltl::unabbreviate_logic(ftmp3);
|
||||
ftmp1 = spot::ltl::negative_normal_form(ftmp2);
|
||||
|
||||
ftmp5 = spot::ltl::unabbreviate_logic(ftmp4);
|
||||
ftmp6 = spot::ltl::negative_normal_form(ftmp5);
|
||||
|
||||
if (n == 0)
|
||||
retour = inf_form(ftmp1, ftmp6);
|
||||
else
|
||||
retour = inf_form(ftmp6, ftmp1);
|
||||
|
||||
spot::ltl::destroy(ftmp1);
|
||||
spot::ltl::destroy(ftmp2);
|
||||
spot::ltl::destroy(ftmp3);
|
||||
spot::ltl::destroy(ftmp4);
|
||||
spot::ltl::destroy(ftmp5);
|
||||
spot::ltl::destroy(ftmp6);
|
||||
|
||||
return retour;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
103
src/ltlvisit/formlength.cc
Normal file
103
src/ltlvisit/formlength.cc
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
// Copyright (C) 2003 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
// 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 "reducform.hh"
|
||||
#include "ltlast/allnodes.hh"
|
||||
#include <cassert>
|
||||
|
||||
#include "lunabbrev.hh"
|
||||
#include "nenoform.hh"
|
||||
#include "ltlvisit/destroy.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
|
||||
class length_form_visitor : public const_visitor
|
||||
{
|
||||
public:
|
||||
|
||||
length_form_visitor()
|
||||
{
|
||||
result_ = 0;
|
||||
}
|
||||
|
||||
virtual ~length_form_visitor()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
result() const
|
||||
{
|
||||
return result_;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const atomic_prop* ap)
|
||||
{
|
||||
if (ap);
|
||||
result_ = 1;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const constant* c)
|
||||
{
|
||||
if (c);
|
||||
result_ = 1;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const unop* uo)
|
||||
{
|
||||
if (uo);
|
||||
result_ = 1 + form_length(uo->child());
|
||||
}
|
||||
|
||||
void
|
||||
visit(const binop* bo)
|
||||
{
|
||||
if (bo);
|
||||
result_ = 1 + form_length(bo->first()) + form_length(bo->second());
|
||||
}
|
||||
|
||||
void
|
||||
visit(const multop* mo)
|
||||
{
|
||||
unsigned mos = mo->size();
|
||||
for (unsigned i = 0; i < mos; ++i)
|
||||
result_ += form_length(mo->nth(i));
|
||||
}
|
||||
|
||||
protected:
|
||||
int result_; // size of the formula
|
||||
};
|
||||
|
||||
int
|
||||
form_length(const formula* f)
|
||||
{
|
||||
length_form_visitor v;
|
||||
const_cast<formula*>(f)->accept(v);
|
||||
return v.result();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -22,12 +22,58 @@
|
|||
#include "ltlast/allnodes.hh"
|
||||
#include "ltlvisit/clone.hh"
|
||||
#include "lunabbrev.hh"
|
||||
//#include "reducform.hh"
|
||||
#include <cassert>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
|
||||
class node_type_form_visitor : public const_visitor
|
||||
{
|
||||
public:
|
||||
enum type { Atom, Const, Unop, Binop, Multop };
|
||||
|
||||
node_type_form_visitor(){}
|
||||
|
||||
type
|
||||
result() const { return result_;}
|
||||
|
||||
void
|
||||
visit(const atomic_prop* ap){
|
||||
if (ap == NULL);
|
||||
result_ = node_type_form_visitor::Atom;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const constant* c){
|
||||
if (c == NULL);
|
||||
result_ = node_type_form_visitor::Const;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const unop* uo){
|
||||
if (uo == NULL);
|
||||
result_ = node_type_form_visitor::Unop;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const binop* bo){
|
||||
if (bo == NULL);
|
||||
result_ = node_type_form_visitor::Binop;
|
||||
}
|
||||
|
||||
void
|
||||
visit(const multop* mo){
|
||||
if (mo == NULL);
|
||||
result_ = node_type_form_visitor::Multop;
|
||||
}
|
||||
|
||||
protected:
|
||||
type result_;
|
||||
};
|
||||
|
||||
unabbreviate_logic_visitor::unabbreviate_logic_visitor()
|
||||
{
|
||||
}
|
||||
|
|
@ -36,11 +82,38 @@ namespace spot
|
|||
{
|
||||
}
|
||||
|
||||
/*
|
||||
void
|
||||
unabbreviate_logic_visitor::visit(unop* uo)
|
||||
{
|
||||
formula* f = uo->child();
|
||||
switch (uo->op())
|
||||
{
|
||||
case unop::Not:
|
||||
case unop::X:
|
||||
result_ = unop::instance(uo->op(),recurse(f));
|
||||
return;
|
||||
case unop::F:
|
||||
result_ = binop::instance(binop::U,constant::true_instance(),recurse(f));
|
||||
return;
|
||||
case unop::G:
|
||||
result_ = binop::instance(binop::R,constant::false_instance(),recurse(f));
|
||||
return;
|
||||
}
|
||||
// Unreachable code.
|
||||
assert(0);
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
unabbreviate_logic_visitor::visit(binop* bo)
|
||||
{
|
||||
formula* f1 = recurse(bo->first());
|
||||
formula* f2 = recurse(bo->second());
|
||||
|
||||
node_type_form_visitor v;
|
||||
const_cast<formula*>(f1)->accept(v);
|
||||
|
||||
switch (bo->op())
|
||||
{
|
||||
/* f1 ^ f2 == (f1 & !f2) | (f2 & !f1) */
|
||||
|
|
@ -69,10 +142,24 @@ namespace spot
|
|||
unop::instance(unop::Not,
|
||||
f2)));
|
||||
return;
|
||||
/* f1 U f2 == f1 U f2 */
|
||||
/* f1 R f2 == f1 R f2 */
|
||||
|
||||
/* true U f2 == F(f2) */
|
||||
case binop::U:
|
||||
if ( v.result() == node_type_form_visitor::Const )
|
||||
if ( ((constant*)f1)->val() == constant::True ) {
|
||||
result_ = unop::instance(unop::F,f2);
|
||||
return;
|
||||
}
|
||||
result_ = binop::instance(bo->op(), f1, f2);
|
||||
return;
|
||||
|
||||
/* false R f2 == G(f2) */
|
||||
case binop::R:
|
||||
if ( v.result() == node_type_form_visitor::Const )
|
||||
if ( ((constant*)f1)->val() == constant::False ) {
|
||||
result_ = unop::instance(unop::G,f2);
|
||||
return;
|
||||
}
|
||||
result_ = binop::instance(bo->op(), f1, f2);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ namespace spot
|
|||
virtual ~unabbreviate_logic_visitor();
|
||||
|
||||
using super::visit;
|
||||
//void visit(unop* uo);
|
||||
void visit(binop* bo);
|
||||
|
||||
virtual formula* recurse(formula* f);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ namespace spot
|
|||
/// or spot::ltl::unabbreviate_ltl first. (Calling these functions
|
||||
/// after spot::ltl::negative_normal_form would likely produce a
|
||||
/// formula which is not in negative normal form.)
|
||||
|
||||
formula* negative_normal_form(const formula* f, bool negated = false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
392
src/ltlvisit/reducform.cc
Normal file
392
src/ltlvisit/reducform.cc
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
// Copyright (C) 2003 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
// 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 "reducform.hh"
|
||||
#include "ltlast/allnodes.hh"
|
||||
#include <cassert>
|
||||
|
||||
#include "lunabbrev.hh"
|
||||
#include "nenoform.hh"
|
||||
#include "ltlvisit/destroy.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
|
||||
|
||||
//class unabbreviate_FG_visitor::unabbreviate_logic_visitor()
|
||||
|
||||
class reduce_form_visitor : public visitor
|
||||
{
|
||||
public:
|
||||
|
||||
reduce_form_visitor()
|
||||
{
|
||||
/*
|
||||
eventuality_ = false;
|
||||
universality_ = false;
|
||||
*/
|
||||
}
|
||||
|
||||
virtual ~reduce_form_visitor()
|
||||
{
|
||||
}
|
||||
|
||||
formula*
|
||||
result() const
|
||||
{
|
||||
return result_;
|
||||
}
|
||||
|
||||
/*
|
||||
bool
|
||||
is_eventuality()
|
||||
{
|
||||
return eventuality_;
|
||||
}
|
||||
|
||||
bool
|
||||
is_universality()
|
||||
{
|
||||
return universality_;
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
visit(atomic_prop* ap)
|
||||
{
|
||||
formula* f = ap->ref();
|
||||
result_ = f;
|
||||
}
|
||||
|
||||
void
|
||||
visit(constant* c)
|
||||
{
|
||||
switch (c->val())
|
||||
{
|
||||
case constant::True:
|
||||
result_ = constant::true_instance();
|
||||
return;
|
||||
case constant::False:
|
||||
result_ = constant::false_instance();
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(unop* uo)
|
||||
{
|
||||
result_ = recurse(uo->child());
|
||||
|
||||
switch (uo->op())
|
||||
{
|
||||
case unop::Not:
|
||||
result_ = unop::instance(unop::Not, result_);
|
||||
return;
|
||||
|
||||
case unop::X:
|
||||
result_ = unop::instance(unop::X, result_);
|
||||
return;
|
||||
|
||||
case unop::F:
|
||||
/* if f is class of eventuality then F(f)=f */
|
||||
if (!is_eventual(result_)) {
|
||||
result_ = unop::instance(unop::F, result_);
|
||||
}
|
||||
return;
|
||||
|
||||
case unop::G:
|
||||
/* if f is class of universality then G(f)=f */
|
||||
if (!is_universal(result_)) {
|
||||
result_ = unop::instance(unop::G, result_);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(binop* bo)
|
||||
{
|
||||
formula* f2 = recurse(bo->second());
|
||||
|
||||
/* if b is of class eventuality then a U b = b
|
||||
if b is of class universality then a R b = b */
|
||||
if ( ( is_eventual(f2) && ( (bo->op()) == binop::U )) ||
|
||||
( is_universal(f2) && ( (bo->op()) == binop::R )) )
|
||||
{
|
||||
result_ = f2;
|
||||
return;
|
||||
}
|
||||
|
||||
/* case of implies */
|
||||
formula* f1 = recurse(bo->first());
|
||||
bool inf = inf_form(f1,f2);
|
||||
bool infinv = inf_form(f2,f1);
|
||||
//binop* ftmp = NULL;
|
||||
bool infnegleft = infneg_form(f2,f1,0);
|
||||
bool infnegright = infneg_form(f2,f1,1);
|
||||
|
||||
switch (bo->op())
|
||||
{
|
||||
case binop::Xor:
|
||||
case binop::Equiv:
|
||||
case binop::Implies:
|
||||
result_ = binop::instance(bo->op(), f1, f2);
|
||||
return;
|
||||
|
||||
case binop::U:
|
||||
/* a < b => a U b = b */
|
||||
if (inf)
|
||||
{
|
||||
result_ = f2;
|
||||
spot::ltl::destroy(f1);
|
||||
return;
|
||||
}
|
||||
/* !b < a => a U b = Fb */
|
||||
if (infnegleft)
|
||||
{
|
||||
result_ = unop::instance(unop::F, f2);
|
||||
spot::ltl::destroy(f1);
|
||||
return;
|
||||
}
|
||||
/* a < b => a U (b U c) = (b U c) */
|
||||
if (node_type(f2) == node_type_form_visitor::Binop)
|
||||
if (((binop*)f2)->op() == binop::U)
|
||||
if (inf_form(f1,((binop*)f2)->first())){
|
||||
result_ = f2;
|
||||
spot::ltl::destroy(f1);
|
||||
return;
|
||||
}
|
||||
result_ = binop::instance(binop::U,
|
||||
f1, f2);
|
||||
return;
|
||||
|
||||
case binop::R:
|
||||
/* b < a => a R b = b */
|
||||
if (infinv)
|
||||
{
|
||||
result_ = f2;
|
||||
spot::ltl::destroy(f1);
|
||||
return;
|
||||
}
|
||||
/* b < !a => a R b = Gb */
|
||||
if (infnegright)
|
||||
{
|
||||
result_ = unop::instance(unop::G, f2);
|
||||
spot::ltl::destroy(f1);
|
||||
return;
|
||||
}
|
||||
/* b < a => a R (b R c) = b R c */
|
||||
if (node_type(f2) == node_type_form_visitor::Binop)
|
||||
if (((binop*)f2)->op() == binop::R)
|
||||
if (inf_form(((binop*)f2)->first(),f1)){
|
||||
result_ = f2;
|
||||
spot::ltl::destroy(f1);
|
||||
return;
|
||||
}
|
||||
|
||||
result_ = binop::instance(binop::R,
|
||||
f1, f2);
|
||||
return;
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
visit(multop* mo)
|
||||
{
|
||||
formula* f1 = NULL;
|
||||
formula* f2 = NULL;
|
||||
unsigned mos = mo->size();
|
||||
multop::vec* res = new multop::vec;
|
||||
multop::vec::iterator index;
|
||||
multop::vec::iterator indextmp;
|
||||
|
||||
for (unsigned i = 0; i < mos; ++i)
|
||||
res->push_back(recurse(mo->nth(i)));
|
||||
|
||||
switch (mo->op())
|
||||
{
|
||||
|
||||
case multop::Or:
|
||||
index = indextmp = res->begin();
|
||||
if (index != res->end())
|
||||
{
|
||||
f1 = *index;
|
||||
index++;
|
||||
}
|
||||
for (; index != res->end();index++)
|
||||
{
|
||||
f2 = *index;
|
||||
/* a < b => a + b = b */
|
||||
if (inf_form(f1,f2)) // f1 < f2
|
||||
{
|
||||
f1 = f2;
|
||||
spot::ltl::destroy(*indextmp);
|
||||
res->erase(indextmp);
|
||||
indextmp = index;
|
||||
index--;
|
||||
}
|
||||
else if (inf_form(f2,f1)) // f2 < f1
|
||||
{
|
||||
spot::ltl::destroy(*index);
|
||||
res->erase(index);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case multop::And:
|
||||
index = indextmp = res->begin();
|
||||
if (mos)
|
||||
{
|
||||
f1 = mo->nth(0);
|
||||
index++;
|
||||
}
|
||||
for (; index != res->end(); index++)
|
||||
{
|
||||
f2 = *index;
|
||||
/* a < b => a & b = a */
|
||||
if (inf_form(f1,f2)) // f1 < f2
|
||||
{
|
||||
spot::ltl::destroy(*index);
|
||||
res->erase(index);
|
||||
index--;
|
||||
}
|
||||
else if (inf_form(f2,f1)) // f2 < f1
|
||||
{
|
||||
f1 = f2;
|
||||
spot::ltl::destroy(*indextmp);
|
||||
res->erase(indextmp);
|
||||
indextmp = index;
|
||||
index--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* f1 < !f2 => f1 & f2 = false
|
||||
!f1 < f2 => f1 | f2 = true */
|
||||
|
||||
for (index = res->begin(); index != res->end(); index++){
|
||||
for (indextmp = res->begin(); indextmp != res->end(); indextmp++){
|
||||
if (index != indextmp){
|
||||
if (infneg_form(*index,*indextmp, (mo->op() == multop::Or) ? 0 : 1)) {
|
||||
for (multop::vec::iterator j = res->begin(); j != res->end(); j++){
|
||||
spot::ltl::destroy(*j);
|
||||
}
|
||||
if (mo->op() == multop::Or)
|
||||
result_ = constant::true_instance();
|
||||
else
|
||||
result_ = constant::false_instance();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
if ((constant*)(*index) != NULL)
|
||||
if (((((constant*)(*index))->val() == constant::True) &&
|
||||
(mo->op() == multop::Or)) ||
|
||||
(((((constant*)(*index))->val() == constant::False))
|
||||
&& (mo->op() == multop::And))
|
||||
) {
|
||||
//std::cout << "constant" << std::endl;
|
||||
for (multop::vec::iterator j = res->begin(); j != res->end(); j++){
|
||||
spot::ltl::destroy(*j);
|
||||
}
|
||||
if (mo->op() == multop::Or)
|
||||
result_ = constant::true_instance();
|
||||
else
|
||||
result_ = constant::false_instance();
|
||||
|
||||
std::cout << "2" << std::endl;
|
||||
spot::ltl::dump(std::cout,mo);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (res->size()) {
|
||||
result_ = multop::instance(mo->op(),res);
|
||||
return;
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
formula*
|
||||
recurse(formula* f)
|
||||
{
|
||||
return reduce_form(f);
|
||||
}
|
||||
|
||||
protected:
|
||||
formula* result_;
|
||||
/*
|
||||
bool eventuality_;
|
||||
bool universality_;
|
||||
*/
|
||||
};
|
||||
|
||||
formula*
|
||||
reduce_form(const formula* f)
|
||||
{
|
||||
spot::ltl::formula* ftmp1;
|
||||
spot::ltl::formula* ftmp2;
|
||||
reduce_form_visitor v;
|
||||
|
||||
ftmp1 = spot::ltl::basic_reduce_form(f);
|
||||
const_cast<formula*>(ftmp1)->accept(v);
|
||||
ftmp2 = spot::ltl::basic_reduce_form(v.result());
|
||||
|
||||
spot::ltl::destroy(ftmp1);
|
||||
spot::ltl::destroy(v.result());
|
||||
|
||||
return ftmp2;
|
||||
}
|
||||
|
||||
formula*
|
||||
reduce(const formula* f)
|
||||
{
|
||||
spot::ltl::formula* ftmp1;
|
||||
spot::ltl::formula* ftmp2;
|
||||
spot::ltl::formula* ftmp3;
|
||||
|
||||
ftmp1 = spot::ltl::unabbreviate_logic(f);
|
||||
ftmp2 = spot::ltl::negative_normal_form(ftmp1);
|
||||
ftmp3 = spot::ltl::reduce_form(ftmp2);
|
||||
|
||||
spot::ltl::destroy(ftmp1);
|
||||
spot::ltl::destroy(ftmp2);
|
||||
|
||||
return ftmp3;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
86
src/ltlvisit/reducform.hh
Normal file
86
src/ltlvisit/reducform.hh
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (C) 2003 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef SPOT_LTLVISIT_REDUCFORM_HH
|
||||
# define SPOT_LTLVISIT_REDUCFORM_HH
|
||||
|
||||
#include "ltlast/formula.hh"
|
||||
#include "ltlast/visitor.hh"
|
||||
|
||||
// For debog
|
||||
#include "ltlvisit/dump.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
formula* reduce(const formula* f);
|
||||
|
||||
/* Basic rewriting */
|
||||
formula* basic_reduce_form(const formula* f);
|
||||
|
||||
/* formula rewriting using univerality, eventuality,
|
||||
implies and basic_reduce_form */
|
||||
formula* reduce_form(const formula* f);
|
||||
|
||||
/* detect easy case of implies */
|
||||
bool inf_form(const formula* f1, const formula* f2);
|
||||
/* true if f1 < f2, false otherwise */
|
||||
bool infneg_form(const formula* f1, const formula* f2, int n);
|
||||
/* true if !f1 < f2, false otherwise */
|
||||
|
||||
/* detect if a formula is of class eventuality or universality */
|
||||
bool is_eventual(const formula* f);
|
||||
bool is_universal(const formula* f);
|
||||
|
||||
/* detect if a formula is of form GF or FG */
|
||||
bool is_GF(const formula* f);
|
||||
bool is_FG(const formula* f);
|
||||
|
||||
/* To know the first node of a formula */
|
||||
|
||||
class node_type_form_visitor : public const_visitor
|
||||
{
|
||||
public:
|
||||
enum type { Atom, Const, Unop, Binop, Multop };
|
||||
node_type_form_visitor();
|
||||
virtual ~node_type_form_visitor(){};
|
||||
type result() const;
|
||||
void visit(const atomic_prop* ap);
|
||||
void visit(const constant* c);
|
||||
void visit(const unop* uo);
|
||||
void visit(const binop* bo);
|
||||
void visit(const multop* mo);
|
||||
protected:
|
||||
type result_;
|
||||
};
|
||||
|
||||
node_type_form_visitor::type node_type(const formula* f);
|
||||
|
||||
/* Obsolete */
|
||||
int nb_term_multop(const formula* f);
|
||||
formula* reduce_inf_form(const formula* f); /* Obsolete */
|
||||
int form_length(const formula* f); /* For test */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SPOT_LTLVISIT_REDUCFORM_HH
|
||||
Loading…
Add table
Add a link
Reference in a new issue