Teach the DVE2 interface about atomic propositions such as "a <=
10" or "b != 3". This only work for integer variables presently. * iface/dve2/dve2.hh (load_dve2): Take an atomic_prop_set argument to indicate the AP to observe. * iface/dve2/dve2.cc (convert_aps): New function. Parse the atomic propositions in format them in a prop_set structure that will allow fast generation of the state condition. (load_dve2): Call convert_aps, and pass the resulting prop_set structure to the kripke object. (dve2_kripke::dve2_kripke): Store the prop_set structure. (dve2_kripke::~dve2_kripke): Release the prop_set, and unregister the bdd_variable associated to it. (compute_state_condition): New method that uses the prop_set. (succ_iter, state_condition): Call compute_state_condition(). * iface/dve2/dve2check.cc: Adjust the call to load_dve2 to pass it atomic propositions read from the command line.
This commit is contained in:
parent
5a76a7bb05
commit
8136bd412d
4 changed files with 278 additions and 13 deletions
20
ChangeLog
20
ChangeLog
|
|
@ -1,3 +1,23 @@
|
||||||
|
2011-03-05 Alexandre Duret-Lutz <adl@lrde.epita.fr>
|
||||||
|
|
||||||
|
Teach the DVE2 interface about atomic propositions such as "a <=
|
||||||
|
10" or "b != 3". This only work for integer variables presently.
|
||||||
|
|
||||||
|
* iface/dve2/dve2.hh (load_dve2): Take an atomic_prop_set
|
||||||
|
argument to indicate the AP to observe.
|
||||||
|
* iface/dve2/dve2.cc (convert_aps): New function. Parse the
|
||||||
|
atomic propositions in format them in a prop_set structure that
|
||||||
|
will allow fast generation of the state condition.
|
||||||
|
(load_dve2): Call convert_aps, and pass the resulting prop_set
|
||||||
|
structure to the kripke object.
|
||||||
|
(dve2_kripke::dve2_kripke): Store the prop_set structure.
|
||||||
|
(dve2_kripke::~dve2_kripke): Release the prop_set, and unregister
|
||||||
|
the bdd_variable associated to it.
|
||||||
|
(compute_state_condition): New method that uses the prop_set.
|
||||||
|
(succ_iter, state_condition): Call compute_state_condition().
|
||||||
|
* iface/dve2/dve2check.cc: Adjust the call to load_dve2 to
|
||||||
|
pass it atomic propositions read from the command line.
|
||||||
|
|
||||||
2011-03-05 Alexandre Duret-Lutz <adl@lrde.epita.fr>
|
2011-03-05 Alexandre Duret-Lutz <adl@lrde.epita.fr>
|
||||||
|
|
||||||
Display states variables in the state label.
|
Display states variables in the state label.
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,174 @@ namespace spot
|
||||||
callback_context::transitions_t::const_iterator it_;
|
callback_context::transitions_t::const_iterator it_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// PREDICATE EVALUATION
|
||||||
|
|
||||||
|
typedef enum { OP_EQ, OP_NE, OP_LT, OP_GT, OP_LE, OP_GE } relop;
|
||||||
|
|
||||||
|
struct one_prop
|
||||||
|
{
|
||||||
|
int var_num;
|
||||||
|
relop op;
|
||||||
|
int val;
|
||||||
|
int bddvar; // if "var_num op val" is true, output bddvar,
|
||||||
|
// else its negation
|
||||||
|
};
|
||||||
|
typedef std::vector<one_prop> prop_set;
|
||||||
|
|
||||||
|
int
|
||||||
|
convert_aps(const ltl::atomic_prop_set* aps,
|
||||||
|
const dve2_interface* d,
|
||||||
|
bdd_dict* dict,
|
||||||
|
prop_set& out)
|
||||||
|
{
|
||||||
|
int errors = 0;
|
||||||
|
|
||||||
|
int state_size = d->get_state_variable_count();
|
||||||
|
std::map<std::string, int> val_n;
|
||||||
|
for (int i = 0; i < state_size; ++i)
|
||||||
|
val_n[d->get_state_variable_name(i)] = i;
|
||||||
|
|
||||||
|
for (ltl::atomic_prop_set::const_iterator ap = aps->begin();
|
||||||
|
ap != aps->end(); ++ap)
|
||||||
|
{
|
||||||
|
std::string str = (*ap)->name();
|
||||||
|
const char* s = str.c_str();
|
||||||
|
|
||||||
|
// Skip any leading blank.
|
||||||
|
while (*s && (*s == ' ' || *s == '\t'))
|
||||||
|
++s;
|
||||||
|
if (!*s)
|
||||||
|
{
|
||||||
|
std::cerr << "Proposition `" << str
|
||||||
|
<< "' cannot be parsed." << std::endl;
|
||||||
|
++errors;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* name = (char*) malloc(str.size() + 1);
|
||||||
|
char* name_p = name;
|
||||||
|
while (*s && (*s != '=') && *s != '<' && *s != '!' && *s != '>')
|
||||||
|
{
|
||||||
|
if (*s == ' ' || *s == '\t')
|
||||||
|
++s;
|
||||||
|
else
|
||||||
|
*name_p++ = *s++;
|
||||||
|
}
|
||||||
|
*name_p = 0;
|
||||||
|
|
||||||
|
if (name == name_p)
|
||||||
|
{
|
||||||
|
std::cerr << "Proposition `" << str
|
||||||
|
<< "' cannot be parsed." << std::endl;
|
||||||
|
free(name);
|
||||||
|
++errors;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup the name
|
||||||
|
std::map<std::string, int>::const_iterator ni = val_n.find(name);
|
||||||
|
if (ni == val_n.end())
|
||||||
|
{
|
||||||
|
std::cerr << "No variable `" << name
|
||||||
|
<< "' found in model (for proposition `"
|
||||||
|
<< str << "')." << std::endl;
|
||||||
|
free(name);
|
||||||
|
++errors;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
if (!*s) // No operator? Assume "!= 0".
|
||||||
|
{
|
||||||
|
int v = dict->register_proposition(*ap, d);
|
||||||
|
one_prop p = { ni->second, OP_NE, 0, v };
|
||||||
|
out.push_back(p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
relop op;
|
||||||
|
|
||||||
|
switch (*s)
|
||||||
|
{
|
||||||
|
case '!':
|
||||||
|
if (s[1] != '=')
|
||||||
|
goto report_error;
|
||||||
|
op = OP_NE;
|
||||||
|
s += 2;
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
if (s[1] != '=')
|
||||||
|
goto report_error;
|
||||||
|
op = OP_EQ;
|
||||||
|
s += 2;
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
if (s[1] == '=')
|
||||||
|
{
|
||||||
|
op = OP_LE;
|
||||||
|
s += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
op = OP_LT;
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
if (s[1] == '=')
|
||||||
|
{
|
||||||
|
op = OP_LE;
|
||||||
|
s += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
op = OP_LT;
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
report_error:
|
||||||
|
std::cerr << "Unexpected `" << s
|
||||||
|
<< "' while parsing atomic proposition `" << str
|
||||||
|
<< "'." << std::endl;
|
||||||
|
++errors;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*s && (*s == ' ' || *s == '\t'))
|
||||||
|
++s;
|
||||||
|
|
||||||
|
char* s_end;
|
||||||
|
int val = strtol(s, &s_end, 10);
|
||||||
|
if (s == s_end)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to parse `" << s
|
||||||
|
<< "' as an integer." << std::endl;
|
||||||
|
++errors;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
s = s_end;
|
||||||
|
while (*s && (*s == ' ' || *s == '\t'))
|
||||||
|
++s;
|
||||||
|
if (*s)
|
||||||
|
{
|
||||||
|
std::cerr << "Unexpected character `" << s
|
||||||
|
<< "' while parsing atomic proposition `" << str
|
||||||
|
<< "'." << std::endl;
|
||||||
|
++errors;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int v = dict->register_proposition(*ap, d);
|
||||||
|
one_prop p = { ni->second, op, val, v };
|
||||||
|
out.push_back(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// KRIPKE
|
// KRIPKE
|
||||||
|
|
||||||
|
|
@ -199,8 +367,8 @@ namespace spot
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
dve2_kripke(const dve2_interface* d, bdd_dict* dict)
|
dve2_kripke(const dve2_interface* d, bdd_dict* dict, const prop_set* ps)
|
||||||
: d_(d), dict_(dict)
|
: d_(d), dict_(dict), ps_(ps)
|
||||||
{
|
{
|
||||||
state_size_ = d_->get_state_variable_count();
|
state_size_ = d_->get_state_variable_count();
|
||||||
|
|
||||||
|
|
@ -212,7 +380,13 @@ namespace spot
|
||||||
~dve2_kripke()
|
~dve2_kripke()
|
||||||
{
|
{
|
||||||
delete[] vname_;
|
delete[] vname_;
|
||||||
|
lt_dlclose(d_->handle);
|
||||||
|
|
||||||
|
dict_->unregister_all_my_variables(d_);
|
||||||
|
|
||||||
delete d_;
|
delete d_;
|
||||||
|
delete ps_;
|
||||||
|
lt_dlexit();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual
|
virtual
|
||||||
|
|
@ -224,6 +398,36 @@ namespace spot
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bdd
|
||||||
|
compute_state_condition(const dve2_state* s) const
|
||||||
|
{
|
||||||
|
bdd res = bddtrue;
|
||||||
|
for (prop_set::const_iterator i = ps_->begin();
|
||||||
|
i != ps_->end(); ++i)
|
||||||
|
{
|
||||||
|
int l = s->vars[(*i).var_num];
|
||||||
|
int r = (*i).val;
|
||||||
|
|
||||||
|
|
||||||
|
bool cond = false;
|
||||||
|
switch ((*i).op)
|
||||||
|
{
|
||||||
|
case OP_EQ: cond = (l == r); break;
|
||||||
|
case OP_NE: cond = (l != r); break;
|
||||||
|
case OP_LT: cond = (l < r); break;
|
||||||
|
case OP_GT: cond = (l > r); break;
|
||||||
|
case OP_LE: cond = (l <= r); break;
|
||||||
|
case OP_GE: cond = (l >= r); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cond)
|
||||||
|
res &= bdd_ithvar((*i).bddvar);
|
||||||
|
else
|
||||||
|
res &= bdd_nithvar((*i).bddvar);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
virtual
|
virtual
|
||||||
dve2_succ_iterator*
|
dve2_succ_iterator*
|
||||||
succ_iter(const state* local_state,
|
succ_iter(const state* local_state,
|
||||||
|
|
@ -238,15 +442,16 @@ namespace spot
|
||||||
(void) t;
|
(void) t;
|
||||||
assert((unsigned)t == cc->transitions.size());
|
assert((unsigned)t == cc->transitions.size());
|
||||||
|
|
||||||
return new dve2_succ_iterator(cc, bddtrue);
|
return new dve2_succ_iterator(cc, compute_state_condition(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual
|
virtual
|
||||||
bdd
|
bdd
|
||||||
state_condition(const state* s) const
|
state_condition(const state* st) const
|
||||||
{
|
{
|
||||||
(void) s;
|
const dve2_state* s = dynamic_cast<const dve2_state*>(st);
|
||||||
return bddfalse;
|
assert(s);
|
||||||
|
return compute_state_condition(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual
|
virtual
|
||||||
|
|
@ -283,6 +488,7 @@ namespace spot
|
||||||
int state_size_;
|
int state_size_;
|
||||||
bdd_dict* dict_;
|
bdd_dict* dict_;
|
||||||
const char** vname_;
|
const char** vname_;
|
||||||
|
const prop_set* ps_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -291,7 +497,8 @@ namespace spot
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// LOADER
|
// LOADER
|
||||||
|
|
||||||
kripke* load_dve2(const std::string& file_arg, bdd_dict* dict, bool verbose)
|
kripke* load_dve2(const std::string& file_arg, bdd_dict* dict,
|
||||||
|
ltl::atomic_prop_set* to_observe, bool verbose)
|
||||||
{
|
{
|
||||||
std::string file;
|
std::string file;
|
||||||
if (file_arg.find_first_of("/\\") != std::string::npos)
|
if (file_arg.find_first_of("/\\") != std::string::npos)
|
||||||
|
|
@ -371,6 +578,17 @@ namespace spot
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new dve2_kripke(d, dict);
|
prop_set* ps = new prop_set;
|
||||||
|
int errors = convert_aps(to_observe, d, dict, *ps);
|
||||||
|
if (errors)
|
||||||
|
{
|
||||||
|
delete ps;
|
||||||
|
dict->unregister_all_my_variables(d);
|
||||||
|
delete d;
|
||||||
|
lt_dlexit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new dve2_kripke(d, dict, ps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,15 @@
|
||||||
# define SPOT_IFACE_DVE2_DVE2_HH
|
# define SPOT_IFACE_DVE2_DVE2_HH
|
||||||
|
|
||||||
#include "kripke/kripke.hh"
|
#include "kripke/kripke.hh"
|
||||||
|
#include "ltlvisit/apcollect.hh"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
kripke* load_dve2(const std::string& file, bdd_dict* dict,
|
kripke* load_dve2(const std::string& file,
|
||||||
|
bdd_dict* dict,
|
||||||
|
ltl::atomic_prop_set* to_observe,
|
||||||
bool verbose = true);
|
bool verbose = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,16 @@
|
||||||
|
|
||||||
#include "dve2.hh"
|
#include "dve2.hh"
|
||||||
#include "tgbaalgos/dotty.hh"
|
#include "tgbaalgos/dotty.hh"
|
||||||
#include "ltlenv/declenv.hh"
|
#include "ltlenv/defaultenv.hh"
|
||||||
|
#include "ltlast/allnodes.hh"
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
spot::ltl::declarative_environment env;
|
spot::ltl::default_environment& env =
|
||||||
|
spot::ltl::default_environment::instance();
|
||||||
|
|
||||||
|
spot::ltl::atomic_prop_set ap;
|
||||||
|
|
||||||
if (argc <= 1)
|
if (argc <= 1)
|
||||||
{
|
{
|
||||||
|
|
@ -35,12 +39,18 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
while (argc > 2)
|
while (argc > 2)
|
||||||
{
|
{
|
||||||
env.declare(argv[argc - 1]);
|
ap.insert(static_cast<spot::ltl::atomic_prop*>
|
||||||
|
(env.require(argv[argc - 1])));
|
||||||
--argc;
|
--argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
spot::bdd_dict* dict = new spot::bdd_dict();
|
spot::bdd_dict* dict = new spot::bdd_dict();
|
||||||
spot::kripke* a = spot::load_dve2(argv[1], dict, true);
|
spot::kripke* a = spot::load_dve2(argv[1], dict, &ap, true);
|
||||||
|
|
||||||
|
for (spot::ltl::atomic_prop_set::const_iterator it = ap.begin();
|
||||||
|
it != ap.end(); ++it)
|
||||||
|
(*it)->destroy();
|
||||||
|
ap.clear();
|
||||||
|
|
||||||
if (!a)
|
if (!a)
|
||||||
{
|
{
|
||||||
|
|
@ -51,5 +61,17 @@ main(int argc, char **argv)
|
||||||
spot::dotty_reachable(std::cout, a);
|
spot::dotty_reachable(std::cout, a);
|
||||||
|
|
||||||
delete a;
|
delete a;
|
||||||
|
|
||||||
|
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);
|
||||||
|
spot::ltl::automatop::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);
|
||||||
|
assert(spot::ltl::automatop::instance_count() == 0);
|
||||||
|
|
||||||
delete dict;
|
delete dict;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue