sanity: replace tabulars by spaces
* spot/ltsmin/ltsmin.cc, spot/mc/ec.hh, spot/mc/intersect.hh, spot/mc/reachability.hh, spot/mc/unionfind.cc, spot/mc/utils.hh, spot/twacube/cube.cc, spot/twacube/twacube.cc, spot/twacube/twacube.hh, spot/twacube_algos/convert.cc, spot/twacube_algos/convert.hh, tests/core/bricks.cc, tests/core/cube.cc, tests/core/twacube.cc, tests/ltsmin/modelcheck.cc: here.
This commit is contained in:
parent
681c2b2011
commit
f04074bd6d
15 changed files with 935 additions and 936 deletions
|
|
@ -1144,9 +1144,8 @@ namespace spot
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//brick::hashset::FastConcurrent<both , both_hasher> ht2;
|
|
||||||
typedef brick::hashset::FastConcurrent<cspins_state,
|
typedef brick::hashset::FastConcurrent<cspins_state,
|
||||||
cspins_state_hasher> cspins_state_map;
|
cspins_state_hasher> cspins_state_map;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// A manager for Cspins states.
|
// A manager for Cspins states.
|
||||||
|
|
@ -1205,9 +1204,9 @@ namespace spot
|
||||||
void dealloc(cspins_state s)
|
void dealloc(cspins_state s)
|
||||||
{
|
{
|
||||||
if (compress_)
|
if (compress_)
|
||||||
msp_.deallocate(s, (s[1]+2)*sizeof(int));
|
msp_.deallocate(s, (s[1]+2)*sizeof(int));
|
||||||
else
|
else
|
||||||
p_.deallocate(s);
|
p_.deallocate(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int size() const
|
unsigned int size() const
|
||||||
|
|
@ -1249,15 +1248,15 @@ namespace spot
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cspins_iterator(cspins_state s,
|
cspins_iterator(cspins_state s,
|
||||||
const spot::spins_interface* d,
|
const spot::spins_interface* d,
|
||||||
cspins_state_manager& manager,
|
cspins_state_manager& manager,
|
||||||
cspins_state_map& map,
|
cspins_state_map& map,
|
||||||
inner_callback_parameters& inner,
|
inner_callback_parameters& inner,
|
||||||
int defvalue,
|
int defvalue,
|
||||||
cube cond,
|
cube cond,
|
||||||
bool compress,
|
bool compress,
|
||||||
bool selfloopize,
|
bool selfloopize,
|
||||||
cubeset& cubeset, int dead_idx)
|
cubeset& cubeset, int dead_idx)
|
||||||
: current_(0), cond_(cond)
|
: current_(0), cond_(cond)
|
||||||
{
|
{
|
||||||
successors_.reserve(10);
|
successors_.reserve(10);
|
||||||
|
|
@ -1270,41 +1269,41 @@ namespace spot
|
||||||
int* ref = s;
|
int* ref = s;
|
||||||
|
|
||||||
if (compress)
|
if (compress)
|
||||||
// already filled by compute_condition
|
// already filled by compute_condition
|
||||||
ref = inner.uncompressed_;
|
ref = inner.uncompressed_;
|
||||||
|
|
||||||
int n = d->get_successors
|
int n = d->get_successors
|
||||||
(nullptr, manager.unbox_state(ref),
|
(nullptr, manager.unbox_state(ref),
|
||||||
[](void* arg, transition_info_t*, int *dst){
|
[](void* arg, transition_info_t*, int *dst){
|
||||||
inner_callback_parameters* inner =
|
inner_callback_parameters* inner =
|
||||||
static_cast<inner_callback_parameters*>(arg);
|
static_cast<inner_callback_parameters*>(arg);
|
||||||
cspins_state s =
|
cspins_state s =
|
||||||
inner->manager->alloc_setup(dst, inner->compressed_,
|
inner->manager->alloc_setup(dst, inner->compressed_,
|
||||||
inner->manager->size() * 2);
|
inner->manager->size() * 2);
|
||||||
auto it = inner->map->insert({s});
|
auto it = inner->map->insert({s});
|
||||||
inner->succ->push_back(*it);
|
inner->succ->push_back(*it);
|
||||||
if (!it.isnew())
|
if (!it.isnew())
|
||||||
inner->manager->dealloc(s);
|
inner->manager->dealloc(s);
|
||||||
},
|
},
|
||||||
&inner);
|
&inner);
|
||||||
if (!n && selfloopize)
|
if (!n && selfloopize)
|
||||||
{
|
{
|
||||||
successors_.push_back(s);
|
successors_.push_back(s);
|
||||||
if (dead_idx != -1)
|
if (dead_idx != -1)
|
||||||
cubeset.set_true_var(cond, dead_idx);
|
cubeset.set_true_var(cond, dead_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void recycle(cspins_state s,
|
void recycle(cspins_state s,
|
||||||
const spot::spins_interface* d,
|
const spot::spins_interface* d,
|
||||||
cspins_state_manager& manager,
|
cspins_state_manager& manager,
|
||||||
cspins_state_map& map,
|
cspins_state_map& map,
|
||||||
inner_callback_parameters& inner,
|
inner_callback_parameters& inner,
|
||||||
int defvalue,
|
int defvalue,
|
||||||
cube cond,
|
cube cond,
|
||||||
bool compress,
|
bool compress,
|
||||||
bool selfloopize,
|
bool selfloopize,
|
||||||
cubeset& cubeset, int dead_idx)
|
cubeset& cubeset, int dead_idx)
|
||||||
{
|
{
|
||||||
cond_ = cond;
|
cond_ = cond;
|
||||||
current_ = 0;
|
current_ = 0;
|
||||||
|
|
@ -1319,35 +1318,35 @@ namespace spot
|
||||||
int* ref = s;
|
int* ref = s;
|
||||||
|
|
||||||
if (compress)
|
if (compress)
|
||||||
// Already filled by compute_condition
|
// Already filled by compute_condition
|
||||||
ref = inner.uncompressed_;
|
ref = inner.uncompressed_;
|
||||||
|
|
||||||
int n = d->get_successors
|
int n = d->get_successors
|
||||||
(nullptr, manager.unbox_state(ref),
|
(nullptr, manager.unbox_state(ref),
|
||||||
[](void* arg, transition_info_t*, int *dst){
|
[](void* arg, transition_info_t*, int *dst){
|
||||||
inner_callback_parameters* inner =
|
inner_callback_parameters* inner =
|
||||||
static_cast<inner_callback_parameters*>(arg);
|
static_cast<inner_callback_parameters*>(arg);
|
||||||
cspins_state s =
|
cspins_state s =
|
||||||
inner->manager->alloc_setup(dst, inner->compressed_,
|
inner->manager->alloc_setup(dst, inner->compressed_,
|
||||||
inner->manager->size() * 2);
|
inner->manager->size() * 2);
|
||||||
auto it = inner->map->insert({s});
|
auto it = inner->map->insert({s});
|
||||||
inner->succ->push_back(*it);
|
inner->succ->push_back(*it);
|
||||||
if (!it.isnew())
|
if (!it.isnew())
|
||||||
inner->manager->dealloc(s);
|
inner->manager->dealloc(s);
|
||||||
},
|
},
|
||||||
&inner);
|
&inner);
|
||||||
if (!n && selfloopize)
|
if (!n && selfloopize)
|
||||||
{
|
{
|
||||||
successors_.push_back(s);
|
successors_.push_back(s);
|
||||||
if (dead_idx != -1)
|
if (dead_idx != -1)
|
||||||
cubeset.set_true_var(cond, dead_idx);
|
cubeset.set_true_var(cond, dead_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~cspins_iterator()
|
~cspins_iterator()
|
||||||
{
|
{
|
||||||
// Do not release successors states, the manager
|
// Do not release successors states, the manager
|
||||||
// will do it on time.
|
// will do it on time.
|
||||||
}
|
}
|
||||||
|
|
||||||
void next()
|
void next()
|
||||||
|
|
@ -1420,20 +1419,20 @@ namespace spot
|
||||||
}
|
}
|
||||||
~kripkecube()
|
~kripkecube()
|
||||||
{
|
{
|
||||||
for (auto i: recycle_)
|
for (auto i: recycle_)
|
||||||
{
|
{
|
||||||
cubeset_.release(i->condition());
|
cubeset_.release(i->condition());
|
||||||
delete i;
|
delete i;
|
||||||
}
|
}
|
||||||
delete inner_.compressed_;
|
delete inner_.compressed_;
|
||||||
delete inner_.uncompressed_;
|
delete inner_.uncompressed_;
|
||||||
}
|
}
|
||||||
|
|
||||||
cspins_state initial()
|
cspins_state initial()
|
||||||
{
|
{
|
||||||
d_->get_initial_state(inner_.uncompressed_);
|
d_->get_initial_state(inner_.uncompressed_);
|
||||||
return manager_.alloc_setup(inner_.uncompressed_, inner_.compressed_,
|
return manager_.alloc_setup(inner_.uncompressed_, inner_.compressed_,
|
||||||
manager_.size() * 2);
|
manager_.size() * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string to_string(const cspins_state s) const
|
std::string to_string(const cspins_state s) const
|
||||||
|
|
@ -1442,13 +1441,13 @@ namespace spot
|
||||||
cspins_state out = manager_.unbox_state(s);
|
cspins_state out = manager_.unbox_state(s);
|
||||||
cspins_state ref = out;
|
cspins_state ref = out;
|
||||||
if (compress_)
|
if (compress_)
|
||||||
{
|
{
|
||||||
manager_.decompress(s, inner_.uncompressed_, manager_.size());
|
manager_.decompress(s, inner_.uncompressed_, manager_.size());
|
||||||
ref = inner_.uncompressed_;
|
ref = inner_.uncompressed_;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < d_->get_state_size(); ++i)
|
for (int i = 0; i < d_->get_state_size(); ++i)
|
||||||
res += (d_->get_state_variable_name(i)) +
|
res += (d_->get_state_variable_name(i)) +
|
||||||
("=" + std::to_string(ref[i])) + ",";
|
("=" + std::to_string(ref[i])) + ",";
|
||||||
res.pop_back();
|
res.pop_back();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -1456,20 +1455,20 @@ namespace spot
|
||||||
cspins_iterator* succ(const cspins_state s)
|
cspins_iterator* succ(const cspins_state s)
|
||||||
{
|
{
|
||||||
if (SPOT_LIKELY(!recycle_.empty()))
|
if (SPOT_LIKELY(!recycle_.empty()))
|
||||||
{
|
{
|
||||||
auto tmp = recycle_.back();
|
auto tmp = recycle_.back();
|
||||||
recycle_.pop_back();
|
recycle_.pop_back();
|
||||||
compute_condition(tmp->condition(), s);
|
compute_condition(tmp->condition(), s);
|
||||||
tmp->recycle(s, d_, manager_, map_, inner_, -1,
|
tmp->recycle(s, d_, manager_, map_, inner_, -1,
|
||||||
tmp->condition(), compress_, selfloopize_,
|
tmp->condition(), compress_, selfloopize_,
|
||||||
cubeset_, dead_idx_);
|
cubeset_, dead_idx_);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
cube cond = cubeset_.alloc();
|
cube cond = cubeset_.alloc();
|
||||||
compute_condition(cond, s);
|
compute_condition(cond, s);
|
||||||
return new cspins_iterator(s, d_, manager_, map_, inner_,
|
return new cspins_iterator(s, d_, manager_, map_, inner_,
|
||||||
-1, cond, compress_, selfloopize_,
|
-1, cond, compress_, selfloopize_,
|
||||||
cubeset_, dead_idx_);
|
cubeset_, dead_idx_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void recycle(cspins_iterator* it)
|
void recycle(cspins_iterator* it)
|
||||||
|
|
@ -1518,80 +1517,80 @@ namespace spot
|
||||||
// State is compressed, uncompress it
|
// State is compressed, uncompress it
|
||||||
if (compress_)
|
if (compress_)
|
||||||
{
|
{
|
||||||
manager_.decompress(s, inner_.uncompressed_+2, manager_.size());
|
manager_.decompress(s, inner_.uncompressed_+2, manager_.size());
|
||||||
vars = inner_.uncompressed_ + 2;
|
vars = inner_.uncompressed_ + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& ap: pset_)
|
for (auto& ap: pset_)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
bool cond = false;
|
bool cond = false;
|
||||||
switch (ap.op)
|
switch (ap.op)
|
||||||
{
|
{
|
||||||
case OP_EQ_VAR:
|
case OP_EQ_VAR:
|
||||||
cond = (ap.lval == vars[ap.rval]);
|
cond = (ap.lval == vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case OP_NE_VAR:
|
case OP_NE_VAR:
|
||||||
cond = (ap.lval != vars[ap.rval]);
|
cond = (ap.lval != vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case OP_LT_VAR:
|
case OP_LT_VAR:
|
||||||
cond = (ap.lval < vars[ap.rval]);
|
cond = (ap.lval < vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case OP_GT_VAR:
|
case OP_GT_VAR:
|
||||||
cond = (ap.lval > vars[ap.rval]);
|
cond = (ap.lval > vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case OP_LE_VAR:
|
case OP_LE_VAR:
|
||||||
cond = (ap.lval <= vars[ap.rval]);
|
cond = (ap.lval <= vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case OP_GE_VAR:
|
case OP_GE_VAR:
|
||||||
cond = (ap.lval >= vars[ap.rval]);
|
cond = (ap.lval >= vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_EQ:
|
case VAR_OP_EQ:
|
||||||
cond = (vars[ap.lval] == ap.rval);
|
cond = (vars[ap.lval] == ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_NE:
|
case VAR_OP_NE:
|
||||||
cond = (vars[ap.lval] != ap.rval);
|
cond = (vars[ap.lval] != ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_LT:
|
case VAR_OP_LT:
|
||||||
cond = (vars[ap.lval] < ap.rval);
|
cond = (vars[ap.lval] < ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_GT:
|
case VAR_OP_GT:
|
||||||
cond = (vars[ap.lval] > ap.rval);
|
cond = (vars[ap.lval] > ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_LE:
|
case VAR_OP_LE:
|
||||||
cond = (vars[ap.lval] <= ap.rval);
|
cond = (vars[ap.lval] <= ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_GE:
|
case VAR_OP_GE:
|
||||||
cond = (vars[ap.lval] >= ap.rval);
|
cond = (vars[ap.lval] >= ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_EQ_VAR:
|
case VAR_OP_EQ_VAR:
|
||||||
cond = (vars[ap.lval] == vars[ap.rval]);
|
cond = (vars[ap.lval] == vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_NE_VAR:
|
case VAR_OP_NE_VAR:
|
||||||
cond = (vars[ap.lval] != vars[ap.rval]);
|
cond = (vars[ap.lval] != vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_LT_VAR:
|
case VAR_OP_LT_VAR:
|
||||||
cond = (vars[ap.lval] < vars[ap.rval]);
|
cond = (vars[ap.lval] < vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_GT_VAR:
|
case VAR_OP_GT_VAR:
|
||||||
cond = (vars[ap.lval] > vars[ap.rval]);
|
cond = (vars[ap.lval] > vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_LE_VAR:
|
case VAR_OP_LE_VAR:
|
||||||
cond = (vars[ap.lval] <= vars[ap.rval]);
|
cond = (vars[ap.lval] <= vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_GE_VAR:
|
case VAR_OP_GE_VAR:
|
||||||
cond = (vars[ap.lval] >= vars[ap.rval]);
|
cond = (vars[ap.lval] >= vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case VAR_DEAD:
|
case VAR_DEAD:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cond)
|
if (cond)
|
||||||
cubeset_.set_true_var(c, i);
|
cubeset_.set_true_var(c, i);
|
||||||
else
|
else
|
||||||
cubeset_.set_false_var(c, i);
|
cubeset_.set_false_var(c, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1615,10 +1614,10 @@ namespace spot
|
||||||
std::unordered_map<std::string, int> matcher;
|
std::unordered_map<std::string, int> matcher;
|
||||||
for (int i = 0; i < type_count; ++i)
|
for (int i = 0; i < type_count; ++i)
|
||||||
{
|
{
|
||||||
matcher[d_->get_type_name(i)] = i;
|
matcher[d_->get_type_name(i)] = i;
|
||||||
int enum_count = d_->get_type_value_count(i);
|
int enum_count = d_->get_type_value_count(i);
|
||||||
for (int j = 0; j < enum_count; ++j)
|
for (int j = 0; j < enum_count; ++j)
|
||||||
enum_map[i].emplace(d_->get_type_value_name(i, j), j);
|
enum_map[i].emplace(d_->get_type_value_name(i, j), j);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then we extract the basic atomics propositions from the Kripke
|
// Then we extract the basic atomics propositions from the Kripke
|
||||||
|
|
@ -1630,308 +1629,308 @@ namespace spot
|
||||||
int i = -1;
|
int i = -1;
|
||||||
for (auto ap: aps)
|
for (auto ap: aps)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
// Grab dead property
|
// Grab dead property
|
||||||
if (ap.compare(dead_prop) == 0)
|
if (ap.compare(dead_prop) == 0)
|
||||||
{
|
{
|
||||||
dead_idx_ = i;
|
dead_idx_ = i;
|
||||||
pset_.push_back({i , VAR_DEAD, 0});
|
pset_.push_back({i , VAR_DEAD, 0});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get ap name and remove all extra whitespace
|
// Get ap name and remove all extra whitespace
|
||||||
ap.erase(std::remove_if(ap.begin(), ap.end(),
|
ap.erase(std::remove_if(ap.begin(), ap.end(),
|
||||||
[](char x){
|
[](char x){
|
||||||
return std::isspace(x);
|
return std::isspace(x);
|
||||||
}),
|
}),
|
||||||
ap.end());
|
ap.end());
|
||||||
|
|
||||||
// Look if it is a well known atomic proposition
|
// Look if it is a well known atomic proposition
|
||||||
auto it = std::find(k_aps.begin(), k_aps.end(), ap);
|
auto it = std::find(k_aps.begin(), k_aps.end(), ap);
|
||||||
if (it != k_aps.end())
|
if (it != k_aps.end())
|
||||||
{
|
{
|
||||||
// The aps is directly an AP of the system, we will just
|
// The aps is directly an AP of the system, we will just
|
||||||
// have to detect if the variable is 0 or not.
|
// have to detect if the variable is 0 or not.
|
||||||
pset_.push_back({(int)std::distance(k_aps.begin(), it),
|
pset_.push_back({(int)std::distance(k_aps.begin(), it),
|
||||||
VAR_OP_NE, 0});
|
VAR_OP_NE, 0});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The ap is not known. We distinguish many cases:
|
// The ap is not known. We distinguish many cases:
|
||||||
// - It is a State name, i.e P_0.S or P_0 == S
|
// - It is a State name, i.e P_0.S or P_0 == S
|
||||||
// - It refers a specific variable value, i.e. P_0.var == 2,
|
// - It refers a specific variable value, i.e. P_0.var == 2,
|
||||||
// P_0.var < 2, P_0.var != 2, ...
|
// P_0.var < 2, P_0.var != 2, ...
|
||||||
// - It's an unknown variable
|
// - It's an unknown variable
|
||||||
// Note that we do not support P_0.state1 == 12 since we do not
|
// Note that we do not support P_0.state1 == 12 since we do not
|
||||||
// know how to interpret such atomic proposition.
|
// know how to interpret such atomic proposition.
|
||||||
|
|
||||||
// We split the formula according to operators
|
// We split the formula according to operators
|
||||||
std::size_t found_op_first = ap.find_first_of("=<>!");
|
std::size_t found_op_first = ap.find_first_of("=<>!");
|
||||||
std::size_t found_op_last = ap.find_last_of("=<>!");
|
std::size_t found_op_last = ap.find_last_of("=<>!");
|
||||||
std::string left;
|
std::string left;
|
||||||
std::string right;
|
std::string right;
|
||||||
std::string ap_error;
|
std::string ap_error;
|
||||||
std::string op;
|
std::string op;
|
||||||
|
|
||||||
if (found_op_first == 0 || found_op_last == ap.size()-1)
|
if (found_op_first == 0 || found_op_last == ap.size()-1)
|
||||||
{
|
{
|
||||||
err << "Invalid operator use in " << ap << '\n';
|
err << "Invalid operator use in " << ap << '\n';
|
||||||
++errors;
|
++errors;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::string::npos == found_op_first)
|
if (std::string::npos == found_op_first)
|
||||||
{
|
{
|
||||||
left = ap;
|
left = ap;
|
||||||
right = "";
|
right = "";
|
||||||
op = "";
|
op = "";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
left = ap.substr(0, found_op_first);
|
left = ap.substr(0, found_op_first);
|
||||||
right = ap.substr(found_op_last+1, ap.size()-found_op_last);
|
right = ap.substr(found_op_last+1, ap.size()-found_op_last);
|
||||||
op = ap.substr(found_op_first, found_op_last+1-found_op_first);
|
op = ap.substr(found_op_first, found_op_last+1-found_op_first);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variables to store the left part of the atomic proposition
|
// Variables to store the left part of the atomic proposition
|
||||||
bool left_is_digit = false;
|
bool left_is_digit = false;
|
||||||
int lval;
|
int lval;
|
||||||
|
|
||||||
// Variables to store the right part of the atomic proposition
|
// Variables to store the right part of the atomic proposition
|
||||||
bool right_is_digit = false;
|
bool right_is_digit = false;
|
||||||
int rval;
|
int rval;
|
||||||
|
|
||||||
// And finally the operator
|
// And finally the operator
|
||||||
relop oper;
|
relop oper;
|
||||||
|
|
||||||
|
|
||||||
// Now, left and (possibly) right are should refer atomic
|
// Now, left and (possibly) right are should refer atomic
|
||||||
// propositions or specific state inside of a process.
|
// propositions or specific state inside of a process.
|
||||||
// First check if it is a known atomic proposition
|
// First check if it is a known atomic proposition
|
||||||
it = std::find(k_aps.begin(), k_aps.end(), left);
|
it = std::find(k_aps.begin(), k_aps.end(), left);
|
||||||
if (it != k_aps.end())
|
if (it != k_aps.end())
|
||||||
{
|
{
|
||||||
// The aps is directly an AP of the system, we will just
|
// The aps is directly an AP of the system, we will just
|
||||||
// have to detect if the variable is 0 or not.
|
// have to detect if the variable is 0 or not.
|
||||||
lval = std::distance(k_aps.begin(), it);
|
lval = std::distance(k_aps.begin(), it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Detect if it is a process state
|
// Detect if it is a process state
|
||||||
std::size_t found_dot = left.find_first_of('.');
|
std::size_t found_dot = left.find_first_of('.');
|
||||||
if (std::string::npos != found_dot)
|
if (std::string::npos != found_dot)
|
||||||
{
|
{
|
||||||
std::string proc_name = left.substr(0, found_dot);
|
std::string proc_name = left.substr(0, found_dot);
|
||||||
std::string st_name = left.substr(found_dot+1,
|
std::string st_name = left.substr(found_dot+1,
|
||||||
left.size()-found_dot);
|
left.size()-found_dot);
|
||||||
|
|
||||||
auto ni = matcher.find(proc_name);
|
auto ni = matcher.find(proc_name);
|
||||||
if (ni == matcher.end())
|
if (ni == matcher.end())
|
||||||
{
|
{
|
||||||
ap_error = left;
|
ap_error = left;
|
||||||
goto error_ap_unknown;
|
goto error_ap_unknown;
|
||||||
}
|
}
|
||||||
int type_num = ni->second;
|
int type_num = ni->second;
|
||||||
enum_map_t::const_iterator ei =
|
enum_map_t::const_iterator ei =
|
||||||
enum_map[type_num].find(st_name);
|
enum_map[type_num].find(st_name);
|
||||||
if (ei == enum_map[type_num].end())
|
if (ei == enum_map[type_num].end())
|
||||||
{
|
{
|
||||||
ap_error = left;
|
ap_error = left;
|
||||||
goto error_ap_unknown;
|
goto error_ap_unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (right.compare("") != 0)
|
if (right.compare("") != 0)
|
||||||
{
|
{
|
||||||
// We are in the case P.state1 == something.. We don't
|
// We are in the case P.state1 == something.. We don't
|
||||||
// know how to interpret this.
|
// know how to interpret this.
|
||||||
ap_error = op + right;
|
ap_error = op + right;
|
||||||
err << "\nOperation " << op << " in \"" << ap_error
|
err << "\nOperation " << op << " in \"" << ap_error
|
||||||
<< "\" is not available for process's state"
|
<< "\" is not available for process's state"
|
||||||
<< " (i.e. " << left << ")\n";
|
<< " (i.e. " << left << ")\n";
|
||||||
++errors;
|
++errors;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pset_.push_back({
|
pset_.push_back({
|
||||||
(int) std::distance(k_aps.begin(),
|
(int) std::distance(k_aps.begin(),
|
||||||
std::find(k_aps.begin(),
|
std::find(k_aps.begin(),
|
||||||
k_aps.end(), proc_name)),
|
k_aps.end(), proc_name)),
|
||||||
VAR_OP_EQ, ei->second});
|
VAR_OP_EQ, ei->second});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Finally, it's a number...
|
// Finally, it's a number...
|
||||||
left_is_digit = true;
|
left_is_digit = true;
|
||||||
for (auto c: left)
|
for (auto c: left)
|
||||||
if (!isdigit(c))
|
if (!isdigit(c))
|
||||||
left_is_digit = false;
|
left_is_digit = false;
|
||||||
|
|
||||||
if (left_is_digit)
|
if (left_is_digit)
|
||||||
lval = std::strtol (left.c_str(), nullptr, 10);
|
lval = std::strtol (left.c_str(), nullptr, 10);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// ... or something like: State1 == P_0
|
// ... or something like: State1 == P_0
|
||||||
// so it doesn't contains '.'
|
// so it doesn't contains '.'
|
||||||
if (std::string::npos != right.find_first_of('.'))
|
if (std::string::npos != right.find_first_of('.'))
|
||||||
{
|
{
|
||||||
err << "\nOperation \"" << right
|
err << "\nOperation \"" << right
|
||||||
<< "\" does not refer a process"
|
<< "\" does not refer a process"
|
||||||
<< " (i.e. " << left << " is not valid)\n";
|
<< " (i.e. " << left << " is not valid)\n";
|
||||||
++errors;
|
++errors;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// or something like: P_0 == State1
|
// or something like: P_0 == State1
|
||||||
auto ni = matcher.find(right);
|
auto ni = matcher.find(right);
|
||||||
if (ni == matcher.end())
|
if (ni == matcher.end())
|
||||||
{
|
{
|
||||||
ap_error = ap;
|
ap_error = ap;
|
||||||
goto error_ap_unknown;
|
goto error_ap_unknown;
|
||||||
}
|
}
|
||||||
int type_num = ni->second;
|
int type_num = ni->second;
|
||||||
enum_map_t::const_iterator ei =
|
enum_map_t::const_iterator ei =
|
||||||
enum_map[type_num].find(left);
|
enum_map[type_num].find(left);
|
||||||
if (ei == enum_map[type_num].end())
|
if (ei == enum_map[type_num].end())
|
||||||
{
|
{
|
||||||
ap_error = left;
|
ap_error = left;
|
||||||
goto error_ap_unknown;
|
goto error_ap_unknown;
|
||||||
}
|
}
|
||||||
pset_.push_back({
|
pset_.push_back({
|
||||||
(int) std::distance(k_aps.begin(),
|
(int) std::distance(k_aps.begin(),
|
||||||
std::find(k_aps.begin(),
|
std::find(k_aps.begin(),
|
||||||
k_aps.end(), right)),
|
k_aps.end(), right)),
|
||||||
VAR_OP_EQ, ei->second});
|
VAR_OP_EQ, ei->second});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here Left is known. Just detect cases where left is digit there is
|
// Here Left is known. Just detect cases where left is digit there is
|
||||||
// no right part.
|
// no right part.
|
||||||
if (left_is_digit && right.empty())
|
if (left_is_digit && right.empty())
|
||||||
{
|
{
|
||||||
ap_error = ap;
|
ap_error = ap;
|
||||||
goto error_ap_unknown;
|
goto error_ap_unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!right.empty() && !op.empty());
|
assert(!right.empty() && !op.empty());
|
||||||
|
|
||||||
// Parse right part of the atomic proposition
|
// Parse right part of the atomic proposition
|
||||||
// Check if it is a known atomic proposition
|
// Check if it is a known atomic proposition
|
||||||
it = std::find(k_aps.begin(), k_aps.end(), right);
|
it = std::find(k_aps.begin(), k_aps.end(), right);
|
||||||
if (it != k_aps.end())
|
if (it != k_aps.end())
|
||||||
{
|
{
|
||||||
// The aps is directly an AP of the system, we will just
|
// The aps is directly an AP of the system, we will just
|
||||||
// have to detect if the variable is 0 or not.
|
// have to detect if the variable is 0 or not.
|
||||||
rval = std::distance(k_aps.begin(), it);
|
rval = std::distance(k_aps.begin(), it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We are is the right part, so if it is a process state
|
// We are is the right part, so if it is a process state
|
||||||
// we do not know how to interpret (xxx == P.state1). Abort
|
// we do not know how to interpret (xxx == P.state1). Abort
|
||||||
std::size_t found_dot = right.find_first_of('.');
|
std::size_t found_dot = right.find_first_of('.');
|
||||||
if (std::string::npos != found_dot)
|
if (std::string::npos != found_dot)
|
||||||
{
|
{
|
||||||
ap_error = left + op;
|
ap_error = left + op;
|
||||||
err << "\nOperation " << op << " in \"" << ap_error
|
err << "\nOperation " << op << " in \"" << ap_error
|
||||||
<< "\" is not available for process's state"
|
<< "\" is not available for process's state"
|
||||||
<< " (i.e. " << right << ")\n";
|
<< " (i.e. " << right << ")\n";
|
||||||
++errors;
|
++errors;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Finally, it's a number
|
// Finally, it's a number
|
||||||
right_is_digit = true;
|
right_is_digit = true;
|
||||||
for (auto c: right)
|
for (auto c: right)
|
||||||
if (!isdigit(c))
|
if (!isdigit(c))
|
||||||
right_is_digit = false;
|
right_is_digit = false;
|
||||||
|
|
||||||
if (right_is_digit)
|
if (right_is_digit)
|
||||||
rval = std::strtol (right.c_str(), nullptr, 10);
|
rval = std::strtol (right.c_str(), nullptr, 10);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (std::string::npos != left.find_first_of('.'))
|
if (std::string::npos != left.find_first_of('.'))
|
||||||
{
|
{
|
||||||
err << "\nProposition \"" << ap
|
err << "\nProposition \"" << ap
|
||||||
<< "\" cannot be interpreted"
|
<< "\" cannot be interpreted"
|
||||||
<< " (i.e. " << op + right << " is not valid)\n";
|
<< " (i.e. " << op + right << " is not valid)\n";
|
||||||
++errors;
|
++errors;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// or something like: P_0 == State1
|
// or something like: P_0 == State1
|
||||||
auto ni = matcher.find(left);
|
auto ni = matcher.find(left);
|
||||||
if (ni == matcher.end())
|
if (ni == matcher.end())
|
||||||
{
|
{
|
||||||
|
|
||||||
ap_error = left;
|
ap_error = left;
|
||||||
goto error_ap_unknown;
|
goto error_ap_unknown;
|
||||||
}
|
}
|
||||||
int type_num = ni->second;
|
int type_num = ni->second;
|
||||||
enum_map_t::const_iterator ei =
|
enum_map_t::const_iterator ei =
|
||||||
enum_map[type_num].find(right);
|
enum_map[type_num].find(right);
|
||||||
if (ei == enum_map[type_num].end())
|
if (ei == enum_map[type_num].end())
|
||||||
{
|
{
|
||||||
ap_error = right;
|
ap_error = right;
|
||||||
goto error_ap_unknown;
|
goto error_ap_unknown;
|
||||||
}
|
}
|
||||||
pset_.push_back({
|
pset_.push_back({
|
||||||
(int) std::distance(k_aps.begin(),
|
(int) std::distance(k_aps.begin(),
|
||||||
std::find(k_aps.begin(),
|
std::find(k_aps.begin(),
|
||||||
k_aps.end(), left)),
|
k_aps.end(), left)),
|
||||||
VAR_OP_EQ, ei->second});
|
VAR_OP_EQ, ei->second});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left_is_digit && right_is_digit)
|
if (left_is_digit && right_is_digit)
|
||||||
{
|
{
|
||||||
err << "\nOperation \"" << op
|
err << "\nOperation \"" << op
|
||||||
<< "\" between two numbers not available"
|
<< "\" between two numbers not available"
|
||||||
<< " (i.e. " << right << " and, "
|
<< " (i.e. " << right << " and, "
|
||||||
<< left << ")\n";
|
<< left << ")\n";
|
||||||
++errors;
|
++errors;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Left and Right are know, just analyse the operator.
|
// Left and Right are know, just analyse the operator.
|
||||||
if (op.compare("==") == 0)
|
if (op.compare("==") == 0)
|
||||||
oper = !left_is_digit && !right_is_digit? VAR_OP_EQ_VAR :
|
oper = !left_is_digit && !right_is_digit? VAR_OP_EQ_VAR :
|
||||||
(left_is_digit? OP_EQ_VAR : VAR_OP_EQ);
|
(left_is_digit? OP_EQ_VAR : VAR_OP_EQ);
|
||||||
else if (op.compare("!=") == 0)
|
else if (op.compare("!=") == 0)
|
||||||
oper = !left_is_digit && !right_is_digit? VAR_OP_NE_VAR :
|
oper = !left_is_digit && !right_is_digit? VAR_OP_NE_VAR :
|
||||||
(left_is_digit? OP_NE_VAR : VAR_OP_NE);
|
(left_is_digit? OP_NE_VAR : VAR_OP_NE);
|
||||||
else if (op.compare("<") == 0)
|
else if (op.compare("<") == 0)
|
||||||
oper = !left_is_digit && !right_is_digit? VAR_OP_LT_VAR :
|
oper = !left_is_digit && !right_is_digit? VAR_OP_LT_VAR :
|
||||||
(left_is_digit? OP_LT_VAR : VAR_OP_LT);
|
(left_is_digit? OP_LT_VAR : VAR_OP_LT);
|
||||||
else if (op.compare(">") == 0)
|
else if (op.compare(">") == 0)
|
||||||
oper = !left_is_digit && !right_is_digit? VAR_OP_GT_VAR :
|
oper = !left_is_digit && !right_is_digit? VAR_OP_GT_VAR :
|
||||||
(left_is_digit? OP_GT_VAR : VAR_OP_GT);
|
(left_is_digit? OP_GT_VAR : VAR_OP_GT);
|
||||||
else if (op.compare("<=") == 0)
|
else if (op.compare("<=") == 0)
|
||||||
oper = !left_is_digit && !right_is_digit? VAR_OP_LE_VAR :
|
oper = !left_is_digit && !right_is_digit? VAR_OP_LE_VAR :
|
||||||
(left_is_digit? OP_LE_VAR : VAR_OP_LE);
|
(left_is_digit? OP_LE_VAR : VAR_OP_LE);
|
||||||
else if (op.compare(">=") == 0)
|
else if (op.compare(">=") == 0)
|
||||||
oper = !left_is_digit && !right_is_digit? VAR_OP_GE_VAR :
|
oper = !left_is_digit && !right_is_digit? VAR_OP_GE_VAR :
|
||||||
(left_is_digit? OP_GE_VAR : VAR_OP_GE);
|
(left_is_digit? OP_GE_VAR : VAR_OP_GE);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err << "\nOperation \"" << op
|
err << "\nOperation \"" << op
|
||||||
<< "\" is unknown\n";
|
<< "\" is unknown\n";
|
||||||
++errors;
|
++errors;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pset_.push_back({lval, oper, rval});
|
pset_.push_back({lval, oper, rval});
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
error_ap_unknown:
|
error_ap_unknown:
|
||||||
err << "\nProposition \"" << ap_error << "\" does not exist\n";
|
err << "\nProposition \"" << ap_error << "\" does not exist\n";
|
||||||
++errors;
|
++errors;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors)
|
if (errors)
|
||||||
|
|
|
||||||
162
spot/mc/ec.hh
162
spot/mc/ec.hh
|
|
@ -31,24 +31,24 @@ namespace spot
|
||||||
/// emptiness check that has been proposed we opted to implement
|
/// emptiness check that has been proposed we opted to implement
|
||||||
/// the Gabow's one.
|
/// the Gabow's one.
|
||||||
template<typename State, typename SuccIterator,
|
template<typename State, typename SuccIterator,
|
||||||
typename StateHash, typename StateEqual>
|
typename StateHash, typename StateEqual>
|
||||||
class ec_renault13lpar : public intersect<State, SuccIterator,
|
class ec_renault13lpar : public intersect<State, SuccIterator,
|
||||||
StateHash, StateEqual,
|
StateHash, StateEqual,
|
||||||
ec_renault13lpar<State, SuccIterator,
|
ec_renault13lpar<State, SuccIterator,
|
||||||
StateHash, StateEqual>>
|
StateHash, StateEqual>>
|
||||||
{
|
{
|
||||||
// Ease the manipulation
|
// Ease the manipulation
|
||||||
using typename intersect<State, SuccIterator, StateHash, StateEqual,
|
using typename intersect<State, SuccIterator, StateHash, StateEqual,
|
||||||
ec_renault13lpar<State, SuccIterator,
|
ec_renault13lpar<State, SuccIterator,
|
||||||
StateHash,
|
StateHash,
|
||||||
StateEqual>>::product_state;
|
StateEqual>>::product_state;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ec_renault13lpar(kripkecube<State, SuccIterator>& sys,
|
ec_renault13lpar(kripkecube<State, SuccIterator>& sys,
|
||||||
twacube* twa)
|
twacube* twa)
|
||||||
: intersect<State, SuccIterator, StateHash, StateEqual,
|
: intersect<State, SuccIterator, StateHash, StateEqual,
|
||||||
ec_renault13lpar<State, SuccIterator,
|
ec_renault13lpar<State, SuccIterator,
|
||||||
StateHash, StateEqual>>(sys, twa),
|
StateHash, StateEqual>>(sys, twa),
|
||||||
acc_(twa->acc())
|
acc_(twa->acc())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -84,13 +84,13 @@ namespace spot
|
||||||
/// to true and both \a newtop and \a newtop_dfsnum have inconsistency
|
/// to true and both \a newtop and \a newtop_dfsnum have inconsistency
|
||||||
/// values.
|
/// values.
|
||||||
bool pop_state(product_state, unsigned top_dfsnum, bool,
|
bool pop_state(product_state, unsigned top_dfsnum, bool,
|
||||||
product_state, unsigned)
|
product_state, unsigned)
|
||||||
{
|
{
|
||||||
if (top_dfsnum == roots_.back().dfsnum)
|
if (top_dfsnum == roots_.back().dfsnum)
|
||||||
{
|
{
|
||||||
roots_.pop_back();
|
roots_.pop_back();
|
||||||
uf_.markdead(top_dfsnum);
|
uf_.markdead(top_dfsnum);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ namespace spot
|
||||||
acc_cond::mark_t cond)
|
acc_cond::mark_t cond)
|
||||||
{
|
{
|
||||||
if (uf_.isdead(dst_dfsnum))
|
if (uf_.isdead(dst_dfsnum))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (!uf_.sameset(dst_dfsnum, roots_.back().dfsnum))
|
while (!uf_.sameset(dst_dfsnum, roots_.back().dfsnum))
|
||||||
{
|
{
|
||||||
|
|
@ -127,18 +127,18 @@ namespace spot
|
||||||
|
|
||||||
// Compute the prefix of the accepting run
|
// Compute the prefix of the accepting run
|
||||||
for (auto& s : this->todo)
|
for (auto& s : this->todo)
|
||||||
res += " " + std::to_string(s.st.st_prop) +
|
res += " " + std::to_string(s.st.st_prop) +
|
||||||
+ "*" + this->sys_.to_string(s.st.st_kripke) + "\n";
|
+ "*" + this->sys_.to_string(s.st.st_kripke) + "\n";
|
||||||
|
|
||||||
// Compute the accepting cycle
|
// Compute the accepting cycle
|
||||||
res += "Cycle:\n";
|
res += "Cycle:\n";
|
||||||
|
|
||||||
struct ctrx_element
|
struct ctrx_element
|
||||||
{
|
{
|
||||||
const product_state* prod_st;
|
const product_state* prod_st;
|
||||||
ctrx_element* parent_st;
|
ctrx_element* parent_st;
|
||||||
SuccIterator* it_kripke;
|
SuccIterator* it_kripke;
|
||||||
std::shared_ptr<trans_index> it_prop;
|
std::shared_ptr<trans_index> it_prop;
|
||||||
};
|
};
|
||||||
std::queue<ctrx_element*> bfs;
|
std::queue<ctrx_element*> bfs;
|
||||||
|
|
||||||
|
|
@ -148,65 +148,65 @@ namespace spot
|
||||||
this->sys_.succ(this->todo.back().st.st_kripke),
|
this->sys_.succ(this->todo.back().st.st_kripke),
|
||||||
this->twa_->succ(this->todo.back().st.st_prop)}));
|
this->twa_->succ(this->todo.back().st.st_prop)}));
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
here:
|
here:
|
||||||
auto* front = bfs.front();
|
auto* front = bfs.front();
|
||||||
bfs.pop();
|
bfs.pop();
|
||||||
// PUSH all successors of the state.
|
// PUSH all successors of the state.
|
||||||
while (!front->it_kripke->done())
|
while (!front->it_kripke->done())
|
||||||
{
|
{
|
||||||
while (!front->it_prop->done())
|
while (!front->it_prop->done())
|
||||||
{
|
{
|
||||||
if (this->twa_->get_cubeset().intersect
|
if (this->twa_->get_cubeset().intersect
|
||||||
(this->twa_->trans_data(front->it_prop).cube_,
|
(this->twa_->trans_data(front->it_prop).cube_,
|
||||||
front->it_kripke->condition()))
|
front->it_kripke->condition()))
|
||||||
{
|
{
|
||||||
const product_state dst = {
|
const product_state dst = {
|
||||||
front->it_kripke->state(),
|
front->it_kripke->state(),
|
||||||
this->twa_->trans_storage(front->it_prop).dst
|
this->twa_->trans_storage(front->it_prop).dst
|
||||||
};
|
};
|
||||||
|
|
||||||
// Skip Unknown states or not same SCC
|
// Skip Unknown states or not same SCC
|
||||||
auto it = this->map.find(dst);
|
auto it = this->map.find(dst);
|
||||||
if (it == this->map.end() ||
|
if (it == this->map.end() ||
|
||||||
!uf_.sameset(it->second,
|
!uf_.sameset(it->second,
|
||||||
this->map[this->todo.back().st]))
|
this->map[this->todo.back().st]))
|
||||||
{
|
{
|
||||||
front->it_prop->next();
|
front->it_prop->next();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a valid transition. If this transition
|
// This is a valid transition. If this transition
|
||||||
// is the one we are looking for, update the counter-
|
// is the one we are looking for, update the counter-
|
||||||
// -example and flush the bfs queue.
|
// -example and flush the bfs queue.
|
||||||
auto mark = this->twa_->trans_data(front->it_prop).acc_;
|
auto mark = this->twa_->trans_data(front->it_prop).acc_;
|
||||||
if (!acc.has(mark))
|
if (!acc.has(mark))
|
||||||
{
|
{
|
||||||
ctrx_element* current = front;
|
ctrx_element* current = front;
|
||||||
while (current != nullptr)
|
while (current != nullptr)
|
||||||
{
|
{
|
||||||
// FIXME also display acc?
|
// FIXME also display acc?
|
||||||
res = res + " " +
|
res = res + " " +
|
||||||
std::to_string(current->prod_st->st_prop) +
|
std::to_string(current->prod_st->st_prop) +
|
||||||
+ "*" +
|
+ "*" +
|
||||||
this->sys_. to_string(current->prod_st
|
this->sys_. to_string(current->prod_st
|
||||||
->st_kripke) +
|
->st_kripke) +
|
||||||
"\n";
|
"\n";
|
||||||
current = current->parent_st;
|
current = current->parent_st;
|
||||||
}
|
}
|
||||||
|
|
||||||
// empty the queue
|
// empty the queue
|
||||||
while (!bfs.empty())
|
while (!bfs.empty())
|
||||||
{
|
{
|
||||||
auto* e = bfs.front();
|
auto* e = bfs.front();
|
||||||
bfs.pop();
|
bfs.pop();
|
||||||
delete e;
|
delete e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update acceptance
|
// update acceptance
|
||||||
acc |= mark;
|
acc |= mark;
|
||||||
if (this->twa_->acc().accepting(acc))
|
if (this->twa_->acc().accepting(acc))
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
const product_state* q = &(it->first);
|
const product_state* q = &(it->first);
|
||||||
ctrx_element* root = new ctrx_element({
|
ctrx_element* root = new ctrx_element({
|
||||||
|
|
@ -242,15 +242,15 @@ namespace spot
|
||||||
virtual std::string stats() override
|
virtual std::string stats() override
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
std::to_string(this->dfs_number) + " unique states visited\n" +
|
std::to_string(this->dfs_number) + " unique states visited\n" +
|
||||||
std::to_string(roots_.size()) +
|
std::to_string(roots_.size()) +
|
||||||
" strongly connected components in search stack\n" +
|
" strongly connected components in search stack\n" +
|
||||||
std::to_string(this->transitions) + " transitions explored\n";
|
std::to_string(this->transitions) + " transitions explored\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool found_ = false; ///< \brief A counterexample is detected?
|
bool found_ = false; ///< \brief A counterexample is detected?
|
||||||
|
|
||||||
struct root_element {
|
struct root_element {
|
||||||
unsigned dfsnum;
|
unsigned dfsnum;
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,8 @@ namespace spot
|
||||||
/// The other template parameters allows to consider any kind
|
/// The other template parameters allows to consider any kind
|
||||||
/// of state (and so any kind of kripke structures).
|
/// of state (and so any kind of kripke structures).
|
||||||
template<typename State, typename SuccIterator,
|
template<typename State, typename SuccIterator,
|
||||||
typename StateHash, typename StateEqual,
|
typename StateHash, typename StateEqual,
|
||||||
typename EmptinessCheck>
|
typename EmptinessCheck>
|
||||||
class SPOT_API intersect
|
class SPOT_API intersect
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -78,64 +78,64 @@ namespace spot
|
||||||
self().setup();
|
self().setup();
|
||||||
product_state initial = {sys_.initial(), twa_->get_initial()};
|
product_state initial = {sys_.initial(), twa_->get_initial()};
|
||||||
if (SPOT_LIKELY(self().push_state(initial, dfs_number+1, 0U)))
|
if (SPOT_LIKELY(self().push_state(initial, dfs_number+1, 0U)))
|
||||||
{
|
{
|
||||||
todo.push_back({initial, sys_.succ(initial.st_kripke),
|
todo.push_back({initial, sys_.succ(initial.st_kripke),
|
||||||
twa_->succ(initial.st_prop)});
|
twa_->succ(initial.st_prop)});
|
||||||
|
|
||||||
// Not going further! It's a product with a single state.
|
// Not going further! It's a product with a single state.
|
||||||
if (todo.back().it_prop->done())
|
if (todo.back().it_prop->done())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
forward_iterators(true);
|
forward_iterators(true);
|
||||||
map[initial] = ++dfs_number;
|
map[initial] = ++dfs_number;
|
||||||
}
|
}
|
||||||
while (!todo.empty())
|
while (!todo.empty())
|
||||||
{
|
{
|
||||||
// Check the kripke is enough since it's the outer loop. More
|
// Check the kripke is enough since it's the outer loop. More
|
||||||
// details in forward_iterators.
|
// details in forward_iterators.
|
||||||
if (todo.back().it_kripke->done())
|
if (todo.back().it_kripke->done())
|
||||||
{
|
{
|
||||||
bool is_init = todo.size() == 1;
|
bool is_init = todo.size() == 1;
|
||||||
auto newtop = is_init? todo.back().st: todo[todo.size() -2].st;
|
auto newtop = is_init? todo.back().st: todo[todo.size() -2].st;
|
||||||
if (SPOT_LIKELY(self().pop_state(todo.back().st,
|
if (SPOT_LIKELY(self().pop_state(todo.back().st,
|
||||||
map[todo.back().st],
|
map[todo.back().st],
|
||||||
is_init,
|
is_init,
|
||||||
newtop,
|
newtop,
|
||||||
map[newtop])))
|
map[newtop])))
|
||||||
{
|
{
|
||||||
sys_.recycle(todo.back().it_kripke);
|
sys_.recycle(todo.back().it_kripke);
|
||||||
// FIXME a local storage for twacube iterator?
|
// FIXME a local storage for twacube iterator?
|
||||||
todo.pop_back();
|
todo.pop_back();
|
||||||
if (SPOT_UNLIKELY(self().counterexample_found()))
|
if (SPOT_UNLIKELY(self().counterexample_found()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
++transitions;
|
++transitions;
|
||||||
product_state dst = {
|
product_state dst = {
|
||||||
todo.back().it_kripke->state(),
|
todo.back().it_kripke->state(),
|
||||||
twa_->trans_storage(todo.back().it_prop).dst
|
twa_->trans_storage(todo.back().it_prop).dst
|
||||||
};
|
};
|
||||||
auto acc = twa_->trans_data(todo.back().it_prop).acc_;
|
auto acc = twa_->trans_data(todo.back().it_prop).acc_;
|
||||||
forward_iterators(false);
|
forward_iterators(false);
|
||||||
auto it = map.find(dst);
|
auto it = map.find(dst);
|
||||||
if (it == map.end())
|
if (it == map.end())
|
||||||
{
|
{
|
||||||
if (SPOT_LIKELY(self().push_state(dst, dfs_number+1, acc)))
|
if (SPOT_LIKELY(self().push_state(dst, dfs_number+1, acc)))
|
||||||
{
|
{
|
||||||
map[dst] = ++dfs_number;
|
map[dst] = ++dfs_number;
|
||||||
todo.push_back({dst, sys_.succ(dst.st_kripke),
|
todo.push_back({dst, sys_.succ(dst.st_kripke),
|
||||||
twa_->succ(dst.st_prop)});
|
twa_->succ(dst.st_prop)});
|
||||||
forward_iterators(true);
|
forward_iterators(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (SPOT_UNLIKELY(self().update(todo.back().st,
|
else if (SPOT_UNLIKELY(self().update(todo.back().st,
|
||||||
dfs_number,
|
dfs_number,
|
||||||
dst, map[dst], acc)))
|
dst, map[dst], acc)))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,8 +158,8 @@ namespace spot
|
||||||
virtual std::string stats()
|
virtual std::string stats()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
std::to_string(dfs_number) + " unique states visited\n" +
|
std::to_string(dfs_number) + " unique states visited\n" +
|
||||||
std::to_string(transitions) + " transitions explored\n";
|
std::to_string(transitions) + " transitions explored\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -175,37 +175,37 @@ namespace spot
|
||||||
|
|
||||||
// Sometimes kripke state may have no successors.
|
// Sometimes kripke state may have no successors.
|
||||||
if (todo.back().it_kripke->done())
|
if (todo.back().it_kripke->done())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// The state has just been push and the 2 iterators intersect.
|
// The state has just been push and the 2 iterators intersect.
|
||||||
// There is no need to move iterators forward.
|
// There is no need to move iterators forward.
|
||||||
assert(!(todo.back().it_prop->done()));
|
assert(!(todo.back().it_prop->done()));
|
||||||
if (just_pushed && twa_->get_cubeset()
|
if (just_pushed && twa_->get_cubeset()
|
||||||
.intersect(twa_->trans_data(todo.back().it_prop).cube_,
|
.intersect(twa_->trans_data(todo.back().it_prop).cube_,
|
||||||
todo.back().it_kripke->condition()))
|
todo.back().it_kripke->condition()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Otherwise we have to compute the next valid successor (if it exits).
|
// Otherwise we have to compute the next valid successor (if it exits).
|
||||||
// This requires two loops. The most inner one is for the twacube since
|
// This requires two loops. The most inner one is for the twacube since
|
||||||
// its costless
|
// its costless
|
||||||
if (todo.back().it_prop->done())
|
if (todo.back().it_prop->done())
|
||||||
todo.back().it_prop->reset();
|
todo.back().it_prop->reset();
|
||||||
else
|
else
|
||||||
todo.back().it_prop->next();
|
todo.back().it_prop->next();
|
||||||
|
|
||||||
while (!todo.back().it_kripke->done())
|
while (!todo.back().it_kripke->done())
|
||||||
{
|
{
|
||||||
while (!todo.back().it_prop->done())
|
while (!todo.back().it_prop->done())
|
||||||
{
|
{
|
||||||
if (SPOT_UNLIKELY(twa_->get_cubeset()
|
if (SPOT_UNLIKELY(twa_->get_cubeset()
|
||||||
.intersect(twa_->trans_data(todo.back().it_prop).cube_,
|
.intersect(twa_->trans_data(todo.back().it_prop).cube_,
|
||||||
todo.back().it_kripke->condition())))
|
todo.back().it_kripke->condition())))
|
||||||
return;
|
return;
|
||||||
todo.back().it_prop->next();
|
todo.back().it_prop->next();
|
||||||
}
|
}
|
||||||
todo.back().it_prop->reset();
|
todo.back().it_prop->reset();
|
||||||
todo.back().it_kripke->next();
|
todo.back().it_kripke->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -219,11 +219,11 @@ namespace spot
|
||||||
{
|
{
|
||||||
bool
|
bool
|
||||||
operator()(const product_state lhs,
|
operator()(const product_state lhs,
|
||||||
const product_state rhs) const
|
const product_state rhs) const
|
||||||
{
|
{
|
||||||
StateEqual equal;
|
StateEqual equal;
|
||||||
return (lhs.st_prop == rhs.st_prop) &&
|
return (lhs.st_prop == rhs.st_prop) &&
|
||||||
equal(lhs.st_kripke, rhs.st_kripke);
|
equal(lhs.st_kripke, rhs.st_kripke);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -232,10 +232,10 @@ namespace spot
|
||||||
size_t
|
size_t
|
||||||
operator()(const product_state that) const
|
operator()(const product_state that) const
|
||||||
{
|
{
|
||||||
// FIXME! wang32_hash(that.st_prop) could have
|
// FIXME! wang32_hash(that.st_prop) could have
|
||||||
// been pre-calculated!
|
// been pre-calculated!
|
||||||
StateHash hasher;
|
StateHash hasher;
|
||||||
return wang32_hash(that.st_prop) ^ hasher(that.st_kripke);
|
return wang32_hash(that.st_prop) ^ hasher(that.st_kripke);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -249,8 +249,8 @@ namespace spot
|
||||||
twacube* twa_;
|
twacube* twa_;
|
||||||
std::vector<todo_element> todo;
|
std::vector<todo_element> todo;
|
||||||
typedef std::unordered_map<const product_state, int,
|
typedef std::unordered_map<const product_state, int,
|
||||||
product_state_hash,
|
product_state_hash,
|
||||||
product_state_equal> visited_map;
|
product_state_equal> visited_map;
|
||||||
visited_map map;
|
visited_map map;
|
||||||
unsigned int dfs_number = 0;
|
unsigned int dfs_number = 0;
|
||||||
unsigned int transitions = 0;
|
unsigned int transitions = 0;
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ namespace spot
|
||||||
/// of a kripkecube. The algorithm uses a single DFS since it
|
/// of a kripkecube. The algorithm uses a single DFS since it
|
||||||
/// is the most efficient in a sequential setting
|
/// is the most efficient in a sequential setting
|
||||||
template<typename State, typename SuccIterator,
|
template<typename State, typename SuccIterator,
|
||||||
typename StateHash, typename StateEqual,
|
typename StateHash, typename StateEqual,
|
||||||
typename Visitor>
|
typename Visitor>
|
||||||
class SPOT_API seq_reach_kripke
|
class SPOT_API seq_reach_kripke
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -59,32 +59,32 @@ namespace spot
|
||||||
visited[initial] = ++dfs_number;
|
visited[initial] = ++dfs_number;
|
||||||
self().push(initial, dfs_number);
|
self().push(initial, dfs_number);
|
||||||
while (!todo.empty())
|
while (!todo.empty())
|
||||||
{
|
{
|
||||||
if (todo.back().it->done())
|
if (todo.back().it->done())
|
||||||
{
|
{
|
||||||
sys_.recycle(todo.back().it);
|
sys_.recycle(todo.back().it);
|
||||||
todo.pop_back();
|
todo.pop_back();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
++transitions;
|
++transitions;
|
||||||
State dst = todo.back().it->state();
|
State dst = todo.back().it->state();
|
||||||
auto it = visited.insert({dst, dfs_number+1});
|
auto it = visited.insert({dst, dfs_number+1});
|
||||||
if (it.second)
|
if (it.second)
|
||||||
{
|
{
|
||||||
++dfs_number;
|
++dfs_number;
|
||||||
self().push(dst, dfs_number);
|
self().push(dst, dfs_number);
|
||||||
self().edge(visited[todo.back().s], dfs_number);
|
self().edge(visited[todo.back().s], dfs_number);
|
||||||
todo.back().it->next();
|
todo.back().it->next();
|
||||||
todo.push_back({dst, sys_.succ(dst)});
|
todo.push_back({dst, sys_.succ(dst)});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self().edge(visited[todo.back().s], visited[dst]);
|
self().edge(visited[todo.back().s], visited[dst]);
|
||||||
todo.back().it->next();
|
todo.back().it->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self().finalize();
|
self().finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ namespace spot
|
||||||
// FIXME: The system already handle a set of visited states so
|
// FIXME: The system already handle a set of visited states so
|
||||||
// this map is redundant: an we avoid this new map?
|
// this map is redundant: an we avoid this new map?
|
||||||
typedef std::unordered_map<const State, int,
|
typedef std::unordered_map<const State, int,
|
||||||
StateHash, StateEqual> visited_map;
|
StateHash, StateEqual> visited_map;
|
||||||
visited_map visited;
|
visited_map visited;
|
||||||
unsigned int dfs_number = 0;
|
unsigned int dfs_number = 0;
|
||||||
unsigned int transitions = 0;
|
unsigned int transitions = 0;
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ namespace spot
|
||||||
else {
|
else {
|
||||||
id[root2] = root1;
|
id[root2] = root1;
|
||||||
if (rk1 == rk2)
|
if (rk1 == rk2)
|
||||||
id[root1] = -(rk1 + 1);
|
id[root1] = -(rk1 + 1);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,18 +27,18 @@
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
template<typename State, typename SuccIterator,
|
template<typename State, typename SuccIterator,
|
||||||
typename StateHash, typename StateEqual>
|
typename StateHash, typename StateEqual>
|
||||||
class SPOT_API kripke_to_twa :
|
class SPOT_API kripke_to_twa :
|
||||||
public seq_reach_kripke<State, SuccIterator,
|
public seq_reach_kripke<State, SuccIterator,
|
||||||
StateHash, StateEqual,
|
StateHash, StateEqual,
|
||||||
kripke_to_twa<State, SuccIterator,
|
kripke_to_twa<State, SuccIterator,
|
||||||
StateHash, StateEqual>>
|
StateHash, StateEqual>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
kripke_to_twa(kripkecube<State, SuccIterator>& sys, bdd_dict_ptr dict)
|
kripke_to_twa(kripkecube<State, SuccIterator>& sys, bdd_dict_ptr dict)
|
||||||
: seq_reach_kripke<State, SuccIterator, StateHash, StateEqual,
|
: seq_reach_kripke<State, SuccIterator, StateHash, StateEqual,
|
||||||
kripke_to_twa<State, SuccIterator,
|
kripke_to_twa<State, SuccIterator,
|
||||||
StateHash, StateEqual>>(sys),
|
StateHash, StateEqual>>(sys),
|
||||||
dict_(dict)
|
dict_(dict)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
@ -57,10 +57,10 @@ namespace spot
|
||||||
// Compute the reverse binder.
|
// Compute the reverse binder.
|
||||||
auto aps = this->sys_.get_ap();
|
auto aps = this->sys_.get_ap();
|
||||||
for (unsigned i = 0; i < aps.size(); ++i)
|
for (unsigned i = 0; i < aps.size(); ++i)
|
||||||
{
|
{
|
||||||
auto k = res_->register_ap(aps[i]);
|
auto k = res_->register_ap(aps[i]);
|
||||||
reverse_binder_.insert({i, k});
|
reverse_binder_.insert({i, k});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void push(State s, unsigned i)
|
void push(State s, unsigned i)
|
||||||
|
|
@ -74,7 +74,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
cubeset cs(this->sys_.get_ap().size());
|
cubeset cs(this->sys_.get_ap().size());
|
||||||
bdd cond = cube_to_bdd(this->todo.back().it->condition(),
|
bdd cond = cube_to_bdd(this->todo.back().it->condition(),
|
||||||
cs, reverse_binder_);
|
cs, reverse_binder_);
|
||||||
res_->new_edge(src, dst, cond);
|
res_->new_edge(src, dst, cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,25 +101,25 @@ namespace spot
|
||||||
|
|
||||||
|
|
||||||
template<typename State, typename SuccIterator,
|
template<typename State, typename SuccIterator,
|
||||||
typename StateHash, typename StateEqual>
|
typename StateHash, typename StateEqual>
|
||||||
class SPOT_API product_to_twa :
|
class SPOT_API product_to_twa :
|
||||||
public intersect<State, SuccIterator,
|
public intersect<State, SuccIterator,
|
||||||
StateHash, StateEqual,
|
StateHash, StateEqual,
|
||||||
product_to_twa<State, SuccIterator,
|
product_to_twa<State, SuccIterator,
|
||||||
StateHash, StateEqual>>
|
StateHash, StateEqual>>
|
||||||
{
|
{
|
||||||
// Ease the manipulation
|
// Ease the manipulation
|
||||||
using typename intersect<State, SuccIterator, StateHash, StateEqual,
|
using typename intersect<State, SuccIterator, StateHash, StateEqual,
|
||||||
product_to_twa<State, SuccIterator,
|
product_to_twa<State, SuccIterator,
|
||||||
StateHash,
|
StateHash,
|
||||||
StateEqual>>::product_state;
|
StateEqual>>::product_state;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
product_to_twa(kripkecube<State, SuccIterator>& sys,
|
product_to_twa(kripkecube<State, SuccIterator>& sys,
|
||||||
twacube* twa)
|
twacube* twa)
|
||||||
: intersect<State, SuccIterator, StateHash, StateEqual,
|
: intersect<State, SuccIterator, StateHash, StateEqual,
|
||||||
product_to_twa<State, SuccIterator,
|
product_to_twa<State, SuccIterator,
|
||||||
StateHash, StateEqual>>(sys, twa)
|
StateHash, StateEqual>>(sys, twa)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,50 +141,50 @@ namespace spot
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto ap : this->twa_->get_ap())
|
for (auto ap : this->twa_->get_ap())
|
||||||
{
|
{
|
||||||
auto idx = res_->register_ap(ap);
|
auto idx = res_->register_ap(ap);
|
||||||
std::cout << ap << idx << std::endl;
|
std::cout << ap << idx << std::endl;
|
||||||
reverse_binder_[i++] = idx;
|
reverse_binder_[i++] = idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool push_state(product_state s, unsigned i, acc_cond::mark_t)
|
bool push_state(product_state s, unsigned i, acc_cond::mark_t)
|
||||||
{
|
{
|
||||||
// push also implies edge (when it's not the initial state)
|
// push also implies edge (when it's not the initial state)
|
||||||
if (this->todo.size())
|
if (this->todo.size())
|
||||||
{
|
{
|
||||||
auto c = this->twa_->get_cubeset()
|
auto c = this->twa_->get_cubeset()
|
||||||
.intersection(this->twa_->trans_data
|
.intersection(this->twa_->trans_data
|
||||||
(this->todo.back().it_prop).cube_,
|
(this->todo.back().it_prop).cube_,
|
||||||
this->todo.back().it_kripke->condition());
|
this->todo.back().it_kripke->condition());
|
||||||
|
|
||||||
bdd x = spot::cube_to_bdd(c, this->twa_->get_cubeset(),
|
bdd x = spot::cube_to_bdd(c, this->twa_->get_cubeset(),
|
||||||
reverse_binder_);
|
reverse_binder_);
|
||||||
this->twa_->get_cubeset().release(c);
|
this->twa_->get_cubeset().release(c);
|
||||||
res_->new_edge(this->map[this->todo.back().st]-1, i-1, x,
|
res_->new_edge(this->map[this->todo.back().st]-1, i-1, x,
|
||||||
this->twa_->trans_data
|
this->twa_->trans_data
|
||||||
(this->todo.back().it_prop).acc_);
|
(this->todo.back().it_prop).acc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned st = res_->new_state();
|
unsigned st = res_->new_state();
|
||||||
names_->push_back(this->sys_.to_string(s.st_kripke) +
|
names_->push_back(this->sys_.to_string(s.st_kripke) +
|
||||||
('*' + std::to_string(s.st_prop)));
|
('*' + std::to_string(s.st_prop)));
|
||||||
assert(st+1 == i);
|
assert(st+1 == i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool update(product_state, unsigned src,
|
bool update(product_state, unsigned src,
|
||||||
product_state, unsigned dst,
|
product_state, unsigned dst,
|
||||||
acc_cond::mark_t cond)
|
acc_cond::mark_t cond)
|
||||||
{
|
{
|
||||||
auto c = this->twa_->get_cubeset()
|
auto c = this->twa_->get_cubeset()
|
||||||
.intersection(this->twa_->trans_data
|
.intersection(this->twa_->trans_data
|
||||||
(this->todo.back().it_prop).cube_,
|
(this->todo.back().it_prop).cube_,
|
||||||
this->todo.back().it_kripke->condition());
|
this->todo.back().it_kripke->condition());
|
||||||
|
|
||||||
bdd x = spot::cube_to_bdd(c, this->twa_->get_cubeset(),
|
bdd x = spot::cube_to_bdd(c, this->twa_->get_cubeset(),
|
||||||
reverse_binder_);
|
reverse_binder_);
|
||||||
this->twa_->get_cubeset().release(c);
|
this->twa_->get_cubeset().release(c);
|
||||||
res_->new_edge(src-1, dst-1, x, cond);
|
res_->new_edge(src-1, dst-1, x, cond);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,9 @@ namespace spot
|
||||||
bool incompatible = false;
|
bool incompatible = false;
|
||||||
for (unsigned int i = 0; i < uint_size_ && !incompatible; ++i)
|
for (unsigned int i = 0; i < uint_size_ && !incompatible; ++i)
|
||||||
{
|
{
|
||||||
true_elt = *(lhs+i) | *(rhs+i);
|
true_elt = *(lhs+i) | *(rhs+i);
|
||||||
false_elt = *(lhs+i+uint_size_) | *(rhs+i+uint_size_);
|
false_elt = *(lhs+i+uint_size_) | *(rhs+i+uint_size_);
|
||||||
incompatible |= (true_elt & false_elt);
|
incompatible |= (true_elt & false_elt);
|
||||||
}
|
}
|
||||||
return !incompatible;
|
return !incompatible;
|
||||||
}
|
}
|
||||||
|
|
@ -91,8 +91,8 @@ namespace spot
|
||||||
auto* res = new unsigned int[2*uint_size_];
|
auto* res = new unsigned int[2*uint_size_];
|
||||||
for (unsigned int i = 0; i < uint_size_; ++i)
|
for (unsigned int i = 0; i < uint_size_; ++i)
|
||||||
{
|
{
|
||||||
res[i] = *(lhs+i) | *(rhs+i);
|
res[i] = *(lhs+i) | *(rhs+i);
|
||||||
res[i+uint_size_] = *(lhs+i+uint_size_) | *(rhs+i+uint_size_);
|
res[i+uint_size_] = *(lhs+i+uint_size_) | *(rhs+i+uint_size_);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -119,11 +119,11 @@ namespace spot
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < 2*uint_size_; ++i)
|
for (unsigned int i = 0; i < 2*uint_size_; ++i)
|
||||||
{
|
{
|
||||||
if (i == uint_size_)
|
if (i == uint_size_)
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
|
|
||||||
for (unsigned x = 0; x < nb_bits_; ++x)
|
for (unsigned x = 0; x < nb_bits_; ++x)
|
||||||
std::cout << ((*(c+i) >> x) & 1);
|
std::cout << ((*(c+i) >> x) & 1);
|
||||||
}
|
}
|
||||||
std::cout << '\n';
|
std::cout << '\n';
|
||||||
}
|
}
|
||||||
|
|
@ -135,24 +135,24 @@ namespace spot
|
||||||
unsigned int cpt = 0;
|
unsigned int cpt = 0;
|
||||||
for (unsigned int i = 0; i < uint_size_; ++i)
|
for (unsigned int i = 0; i < uint_size_; ++i)
|
||||||
{
|
{
|
||||||
for (unsigned x = 0; x < nb_bits_ && cpt != size_; ++x)
|
for (unsigned x = 0; x < nb_bits_ && cpt != size_; ++x)
|
||||||
{
|
{
|
||||||
bool true_var = (*(c+i) >> x) & 1;
|
bool true_var = (*(c+i) >> x) & 1;
|
||||||
bool false_var = (*(c+i+uint_size_) >> x) & 1;
|
bool false_var = (*(c+i+uint_size_) >> x) & 1;
|
||||||
if (true_var)
|
if (true_var)
|
||||||
{
|
{
|
||||||
oss << aps[cpt]
|
oss << aps[cpt]
|
||||||
<< (cpt != (size_ - 1) ? "&": "");
|
<< (cpt != (size_ - 1) ? "&": "");
|
||||||
all_free = false;
|
all_free = false;
|
||||||
}
|
}
|
||||||
else if (false_var)
|
else if (false_var)
|
||||||
{
|
{
|
||||||
oss << '!' << aps[cpt]
|
oss << '!' << aps[cpt]
|
||||||
<< (cpt != (size_ - 1) ? "&": "");
|
<< (cpt != (size_ - 1) ? "&": "");
|
||||||
all_free = false;
|
all_free = false;
|
||||||
}
|
}
|
||||||
++cpt;
|
++cpt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (all_free)
|
if (all_free)
|
||||||
oss << '1';
|
oss << '1';
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ namespace spot
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
transition::transition(const cube& cube,
|
transition::transition(const cube& cube,
|
||||||
acc_cond::mark_t acc):
|
acc_cond::mark_t acc):
|
||||||
cube_(cube), acc_(acc)
|
cube_(cube), acc_(acc)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
@ -104,7 +104,7 @@ namespace spot
|
||||||
|
|
||||||
void
|
void
|
||||||
twacube::create_transition(unsigned int src, const cube& cube,
|
twacube::create_transition(unsigned int src, const cube& cube,
|
||||||
const acc_cond::mark_t& mark, unsigned int dst)
|
const acc_cond::mark_t& mark, unsigned int dst)
|
||||||
{
|
{
|
||||||
theg_.new_edge(src, dst, cube, mark);
|
theg_.new_edge(src, dst, cube, mark);
|
||||||
}
|
}
|
||||||
|
|
@ -121,24 +121,24 @@ namespace spot
|
||||||
unsigned int i = 1;
|
unsigned int i = 1;
|
||||||
while (i <= theg_.num_edges())
|
while (i <= theg_.num_edges())
|
||||||
{
|
{
|
||||||
unsigned int j = i;
|
unsigned int j = i;
|
||||||
|
|
||||||
// Walk first bucket of successors
|
// Walk first bucket of successors
|
||||||
while (j <= theg_.num_edges() &&
|
while (j <= theg_.num_edges() &&
|
||||||
theg_.edge_storage(i).src == theg_.edge_storage(j).src)
|
theg_.edge_storage(i).src == theg_.edge_storage(j).src)
|
||||||
++j;
|
++j;
|
||||||
|
|
||||||
// Remove the next bucket
|
// Remove the next bucket
|
||||||
unsigned int itmp = j;
|
unsigned int itmp = j;
|
||||||
|
|
||||||
// Look if there are some transitions missing in this bucket.
|
// Look if there are some transitions missing in this bucket.
|
||||||
while (j <= theg_.num_edges())
|
while (j <= theg_.num_edges())
|
||||||
{
|
{
|
||||||
if (theg_.edge_storage(i).src == theg_.edge_storage(j).src)
|
if (theg_.edge_storage(i).src == theg_.edge_storage(j).src)
|
||||||
return false;
|
return false;
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
i = itmp;
|
i = itmp;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -150,10 +150,10 @@ namespace spot
|
||||||
os << "init : " << twa.init_ << '\n';
|
os << "init : " << twa.init_ << '\n';
|
||||||
for (unsigned int i = 1; i <= twa.theg_.num_edges(); ++i)
|
for (unsigned int i = 1; i <= twa.theg_.num_edges(); ++i)
|
||||||
os << twa.theg_.edge_storage(i).src << "->"
|
os << twa.theg_.edge_storage(i).src << "->"
|
||||||
<< twa.theg_.edge_storage(i).dst << " : "
|
<< twa.theg_.edge_storage(i).dst << " : "
|
||||||
<< cs.dump(twa.theg_.edge_data(i).cube_, twa.aps_)
|
<< cs.dump(twa.theg_.edge_data(i).cube_, twa.aps_)
|
||||||
<< ' ' << twa.theg_.edge_data(i).acc_
|
<< ' ' << twa.theg_.edge_data(i).acc_
|
||||||
<< '\n';
|
<< '\n';
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ namespace spot
|
||||||
// no-swarming : since twacube are dedicated for parallelism, i.e.
|
// no-swarming : since twacube are dedicated for parallelism, i.e.
|
||||||
// swarming, we expect swarming is activated.
|
// swarming, we expect swarming is activated.
|
||||||
if (SPOT_UNLIKELY(!seed))
|
if (SPOT_UNLIKELY(!seed))
|
||||||
return idx_;
|
return idx_;
|
||||||
// swarming.
|
// swarming.
|
||||||
return (((idx_-st_.succ+1)*seed) % (st_.succ_tail-st_.succ+1)) + st_.succ;
|
return (((idx_-st_.succ+1)*seed) % (st_.succ_tail-st_.succ+1)) + st_.succ;
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ namespace spot
|
||||||
unsigned int get_initial();
|
unsigned int get_initial();
|
||||||
cstate* state_from_int(unsigned int i);
|
cstate* state_from_int(unsigned int i);
|
||||||
void create_transition(unsigned int src, const cube& cube,
|
void create_transition(unsigned int src, const cube& cube,
|
||||||
const acc_cond::mark_t& mark, unsigned int dst);
|
const acc_cond::mark_t& mark, unsigned int dst);
|
||||||
const cubeset& get_cubeset() const;
|
const cubeset& get_cubeset() const;
|
||||||
bool succ_contiguous() const;
|
bool succ_contiguous() const;
|
||||||
typedef digraph<cstate, transition> graph_t;
|
typedef digraph<cstate, transition> graph_t;
|
||||||
|
|
@ -126,12 +126,12 @@ namespace spot
|
||||||
typedef graph_t::edge_storage_t edge_storage_t;
|
typedef graph_t::edge_storage_t edge_storage_t;
|
||||||
const graph_t::edge_storage_t&
|
const graph_t::edge_storage_t&
|
||||||
trans_storage(std::shared_ptr<trans_index> ci,
|
trans_storage(std::shared_ptr<trans_index> ci,
|
||||||
unsigned int seed = 0) const
|
unsigned int seed = 0) const
|
||||||
{
|
{
|
||||||
return theg_.edge_storage(ci->current(seed));
|
return theg_.edge_storage(ci->current(seed));
|
||||||
}
|
}
|
||||||
const transition& trans_data(std::shared_ptr<trans_index> ci,
|
const transition& trans_data(std::shared_ptr<trans_index> ci,
|
||||||
unsigned int seed = 0) const
|
unsigned int seed = 0) const
|
||||||
{
|
{
|
||||||
return theg_.edge_data(ci->current(seed));
|
return theg_.edge_data(ci->current(seed));
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +142,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
friend SPOT_API std::ostream& operator<<(std::ostream& os,
|
friend SPOT_API std::ostream& operator<<(std::ostream& os,
|
||||||
const twacube& twa);
|
const twacube& twa);
|
||||||
private:
|
private:
|
||||||
unsigned int init_;
|
unsigned int init_;
|
||||||
acc_cond acc_;
|
acc_cond acc_;
|
||||||
|
|
|
||||||
|
|
@ -23,45 +23,45 @@
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
spot::cube satone_to_cube(bdd one, cubeset& cubeset,
|
spot::cube satone_to_cube(bdd one, cubeset& cubeset,
|
||||||
std::unordered_map<int, int>& binder)
|
std::unordered_map<int, int>& binder)
|
||||||
{
|
{
|
||||||
auto cube = cubeset.alloc();
|
auto cube = cubeset.alloc();
|
||||||
while (one != bddtrue)
|
while (one != bddtrue)
|
||||||
{
|
{
|
||||||
if (bdd_high(one) == bddfalse)
|
if (bdd_high(one) == bddfalse)
|
||||||
{
|
{
|
||||||
assert(binder.find(bdd_var(one)) != binder.end());
|
assert(binder.find(bdd_var(one)) != binder.end());
|
||||||
cubeset.set_false_var(cube, binder[bdd_var(one)]);
|
cubeset.set_false_var(cube, binder[bdd_var(one)]);
|
||||||
one = bdd_low(one);
|
one = bdd_low(one);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(binder.find(bdd_var(one)) != binder.end());
|
assert(binder.find(bdd_var(one)) != binder.end());
|
||||||
cubeset.set_true_var(cube, binder[bdd_var(one)]);
|
cubeset.set_true_var(cube, binder[bdd_var(one)]);
|
||||||
one = bdd_high(one);
|
one = bdd_high(one);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cube;
|
return cube;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd cube_to_bdd(spot::cube cube, const cubeset& cubeset,
|
bdd cube_to_bdd(spot::cube cube, const cubeset& cubeset,
|
||||||
std::unordered_map<int, int>& reverse_binder)
|
std::unordered_map<int, int>& reverse_binder)
|
||||||
{
|
{
|
||||||
bdd result = bddtrue;
|
bdd result = bddtrue;
|
||||||
for (unsigned int i = 0; i < cubeset.size(); ++i)
|
for (unsigned int i = 0; i < cubeset.size(); ++i)
|
||||||
{
|
{
|
||||||
assert(reverse_binder.find(i) != reverse_binder.end());
|
assert(reverse_binder.find(i) != reverse_binder.end());
|
||||||
if (cubeset.is_false_var(cube, i))
|
if (cubeset.is_false_var(cube, i))
|
||||||
result &= bdd_nithvar(reverse_binder[i]);
|
result &= bdd_nithvar(reverse_binder[i]);
|
||||||
if (cubeset.is_true_var(cube, i))
|
if (cubeset.is_true_var(cube, i))
|
||||||
result &= bdd_ithvar(reverse_binder[i]);
|
result &= bdd_ithvar(reverse_binder[i]);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
spot::twacube* twa_to_twacube(spot::twa_graph_ptr& aut,
|
spot::twacube* twa_to_twacube(spot::twa_graph_ptr& aut,
|
||||||
std::unordered_map<int, int>& ap_binder,
|
std::unordered_map<int, int>& ap_binder,
|
||||||
std::vector<std::string>& aps)
|
std::vector<std::string>& aps)
|
||||||
{
|
{
|
||||||
// Declare the twa cube
|
// Declare the twa cube
|
||||||
spot::twacube* tg = new spot::twacube(aps);
|
spot::twacube* tg = new spot::twacube(aps);
|
||||||
|
|
@ -86,29 +86,29 @@ namespace spot
|
||||||
// spot::cube cube(aps);
|
// spot::cube cube(aps);
|
||||||
for (unsigned n = 0; n < aut->num_states(); ++n)
|
for (unsigned n = 0; n < aut->num_states(); ++n)
|
||||||
for (auto& t: aut->out(n))
|
for (auto& t: aut->out(n))
|
||||||
{
|
{
|
||||||
bdd cond = t.cond;
|
bdd cond = t.cond;
|
||||||
|
|
||||||
// Special case for bddfalse
|
// Special case for bddfalse
|
||||||
if (cond == bddfalse)
|
if (cond == bddfalse)
|
||||||
{
|
{
|
||||||
spot::cube cube = tg->get_cubeset().alloc();
|
spot::cube cube = tg->get_cubeset().alloc();
|
||||||
for (unsigned int i = 0; i < cs.size(); ++i)
|
for (unsigned int i = 0; i < cs.size(); ++i)
|
||||||
cs.set_false_var(cube, i); // FIXME ! use fill!
|
cs.set_false_var(cube, i); // FIXME ! use fill!
|
||||||
tg->create_transition(st_binder[n], cube,
|
tg->create_transition(st_binder[n], cube,
|
||||||
t.acc, st_binder[t.dst]);
|
t.acc, st_binder[t.dst]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// Split the bdd into multiple transitions
|
// Split the bdd into multiple transitions
|
||||||
while (cond != bddfalse)
|
while (cond != bddfalse)
|
||||||
{
|
{
|
||||||
bdd one = bdd_satone(cond);
|
bdd one = bdd_satone(cond);
|
||||||
cond -= one;
|
cond -= one;
|
||||||
spot::cube cube =spot::satone_to_cube(one, cs, ap_binder);
|
spot::cube cube =spot::satone_to_cube(one, cs, ap_binder);
|
||||||
tg->create_transition(st_binder[n], cube, t.acc,
|
tg->create_transition(st_binder[n], cube, t.acc,
|
||||||
st_binder[t.dst]);
|
st_binder[t.dst]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Must be contiguous to support swarming.
|
// Must be contiguous to support swarming.
|
||||||
assert(tg->succ_contiguous());
|
assert(tg->succ_contiguous());
|
||||||
return tg;
|
return tg;
|
||||||
|
|
@ -116,17 +116,17 @@ namespace spot
|
||||||
|
|
||||||
std::vector<std::string>*
|
std::vector<std::string>*
|
||||||
extract_aps(spot::twa_graph_ptr& aut,
|
extract_aps(spot::twa_graph_ptr& aut,
|
||||||
std::unordered_map<int, int>& ap_binder)
|
std::unordered_map<int, int>& ap_binder)
|
||||||
{
|
{
|
||||||
std::vector<std::string>* aps = new std::vector<std::string>();
|
std::vector<std::string>* aps = new std::vector<std::string>();
|
||||||
for (auto f: aut->ap())
|
for (auto f: aut->ap())
|
||||||
{
|
{
|
||||||
int size = aps->size();
|
int size = aps->size();
|
||||||
if (std::find(aps->begin(), aps->end(), f.ap_name()) == aps->end())
|
if (std::find(aps->begin(), aps->end(), f.ap_name()) == aps->end())
|
||||||
{
|
{
|
||||||
aps->push_back(f.ap_name());
|
aps->push_back(f.ap_name());
|
||||||
ap_binder.insert({aut->get_dict()->var_map[f], size});
|
ap_binder.insert({aut->get_dict()->var_map[f], size});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return aps;
|
return aps;
|
||||||
}
|
}
|
||||||
|
|
@ -153,26 +153,26 @@ namespace spot
|
||||||
// Build all resulting states
|
// Build all resulting states
|
||||||
for (unsigned int i = 0; i < theg.num_states(); ++i)
|
for (unsigned int i = 0; i < theg.num_states(); ++i)
|
||||||
{
|
{
|
||||||
unsigned st = res->new_state();
|
unsigned st = res->new_state();
|
||||||
(void) st;
|
(void) st;
|
||||||
assert(st == i);
|
assert(st == i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build all resulting conditions.
|
// Build all resulting conditions.
|
||||||
for (unsigned int i = 1; i <= theg.num_edges(); ++i)
|
for (unsigned int i = 1; i <= theg.num_edges(); ++i)
|
||||||
{
|
{
|
||||||
bdd cond = bddtrue;
|
bdd cond = bddtrue;
|
||||||
for (unsigned j = 0; j < cs.size(); ++j)
|
for (unsigned j = 0; j < cs.size(); ++j)
|
||||||
{
|
{
|
||||||
if (cs.is_true_var(theg.edge_data(i).cube_, j))
|
if (cs.is_true_var(theg.edge_data(i).cube_, j))
|
||||||
cond &= bdd_ithvar(bdds_ref[j]);
|
cond &= bdd_ithvar(bdds_ref[j]);
|
||||||
else if (cs.is_false_var(theg.edge_data(i).cube_, j))
|
else if (cs.is_false_var(theg.edge_data(i).cube_, j))
|
||||||
cond &= bdd_nithvar(bdds_ref[j]);
|
cond &= bdd_nithvar(bdds_ref[j]);
|
||||||
// otherwise it 's a free variable do nothing
|
// otherwise it 's a free variable do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
res->new_edge(theg.edge_storage(i).src, theg.edge_storage(i).dst,
|
res->new_edge(theg.edge_storage(i).src, theg.edge_storage(i).dst,
|
||||||
cond, theg.edge_data(i).acc_);
|
cond, theg.edge_data(i).acc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix the initial state
|
// Fix the initial state
|
||||||
|
|
|
||||||
|
|
@ -33,23 +33,23 @@ namespace spot
|
||||||
/// into a \a cube cube passed in parameter. The parameter
|
/// into a \a cube cube passed in parameter. The parameter
|
||||||
/// \a binder map bdd indexes to cube indexes.
|
/// \a binder map bdd indexes to cube indexes.
|
||||||
SPOT_API spot::cube satone_to_cube(bdd one, cubeset& cubeset,
|
SPOT_API spot::cube satone_to_cube(bdd one, cubeset& cubeset,
|
||||||
std::unordered_map<int, int>& binder);
|
std::unordered_map<int, int>& binder);
|
||||||
|
|
||||||
/// \brief Transform a \a cube cube into bdd using the map
|
/// \brief Transform a \a cube cube into bdd using the map
|
||||||
/// that bind cube indexes to bdd indexes.
|
/// that bind cube indexes to bdd indexes.
|
||||||
SPOT_API bdd cube_to_bdd(spot::cube cube, const cubeset& cubeset,
|
SPOT_API bdd cube_to_bdd(spot::cube cube, const cubeset& cubeset,
|
||||||
std::unordered_map<int, int>& reverse_binder);
|
std::unordered_map<int, int>& reverse_binder);
|
||||||
|
|
||||||
/// \brief Extract the atomic propositions from the automaton
|
/// \brief Extract the atomic propositions from the automaton
|
||||||
SPOT_API std::vector<std::string>*
|
SPOT_API std::vector<std::string>*
|
||||||
extract_aps(spot::twa_graph_ptr& aut,
|
extract_aps(spot::twa_graph_ptr& aut,
|
||||||
std::unordered_map<int, int>& ap_binder);
|
std::unordered_map<int, int>& ap_binder);
|
||||||
|
|
||||||
/// \brief Convert a twa into a twacube
|
/// \brief Convert a twa into a twacube
|
||||||
SPOT_API spot::twacube*
|
SPOT_API spot::twacube*
|
||||||
twa_to_twacube(spot::twa_graph_ptr& aut,
|
twa_to_twacube(spot::twa_graph_ptr& aut,
|
||||||
std::unordered_map<int, int>& ap_binder,
|
std::unordered_map<int, int>& ap_binder,
|
||||||
std::vector<std::string>& aps);
|
std::vector<std::string>& aps);
|
||||||
|
|
||||||
/// \brief Convert a twacube into a twa
|
/// \brief Convert a twacube into a twa
|
||||||
SPOT_API spot::twa_graph_ptr
|
SPOT_API spot::twa_graph_ptr
|
||||||
|
|
|
||||||
|
|
@ -62,10 +62,10 @@ int main()
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
workers.
|
workers.
|
||||||
push_back(std::thread([&ht2](int tid)
|
push_back(std::thread([&ht2](int tid)
|
||||||
{
|
{
|
||||||
for (int i = 0; i< 2000; ++i)
|
for (int i = 0; i< 2000; ++i)
|
||||||
ht2.insert({i, tid});
|
ht2.insert({i, tid});
|
||||||
}, i));
|
}, i));
|
||||||
|
|
||||||
// Wait the end of all threads.
|
// Wait the end of all threads.
|
||||||
for (auto& t: workers)
|
for (auto& t: workers)
|
||||||
|
|
@ -75,6 +75,6 @@ int main()
|
||||||
for (unsigned i = 0; i < ht2.size(); ++ i)
|
for (unsigned i = 0; i < ht2.size(); ++ i)
|
||||||
if (ht2.valid(i))
|
if (ht2.valid(i))
|
||||||
std::cout << i << ": {"
|
std::cout << i << ": {"
|
||||||
<< ht2[i].x << ',' << ht2[i].y << "}\n";
|
<< ht2[i].x << ',' << ht2[i].y << "}\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,9 @@
|
||||||
|
|
||||||
|
|
||||||
static bool test_translation(bdd& input, spot::cubeset& cubeset,
|
static bool test_translation(bdd& input, spot::cubeset& cubeset,
|
||||||
std::unordered_map<int, int>& binder,
|
std::unordered_map<int, int>& binder,
|
||||||
std::unordered_map<int, int>& reverse_binder,
|
std::unordered_map<int, int>& reverse_binder,
|
||||||
std::vector<std::string>& aps)
|
std::vector<std::string>& aps)
|
||||||
{
|
{
|
||||||
// The BDD used to detect if the convertion works
|
// The BDD used to detect if the convertion works
|
||||||
bdd res = bddfalse;
|
bdd res = bddfalse;
|
||||||
|
|
|
||||||
|
|
@ -63,9 +63,9 @@ int main()
|
||||||
auto& t = aut->trans_storage(it, seed);
|
auto& t = aut->trans_storage(it, seed);
|
||||||
auto& d = aut->trans_data(it, seed);
|
auto& d = aut->trans_data(it, seed);
|
||||||
std::cout << t.src << ' ' << t.dst << ' '
|
std::cout << t.src << ' ' << t.dst << ' '
|
||||||
<< ' ' << aut->get_cubeset().dump(d.cube_, *aps)
|
<< ' ' << aut->get_cubeset().dump(d.cube_, *aps)
|
||||||
<< ' ' << d.acc_
|
<< ' ' << d.acc_
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
spot::print_dot(std::cout, spot::twacube_to_twa(aut));
|
spot::print_dot(std::cout, spot::twacube_to_twa(aut));
|
||||||
|
|
|
||||||
|
|
@ -75,17 +75,17 @@ parse_opt_finput(int key, char* arg, struct argp_state*)
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
if (strcmp(arg, "model") == 0)
|
if (strcmp(arg, "model") == 0)
|
||||||
mc_options.dot_output |= DOT_MODEL;
|
mc_options.dot_output |= DOT_MODEL;
|
||||||
else if (strcmp(arg, "product") == 0)
|
else if (strcmp(arg, "product") == 0)
|
||||||
mc_options.dot_output |= DOT_PRODUCT;
|
mc_options.dot_output |= DOT_PRODUCT;
|
||||||
else if (strcmp(arg, "formula") == 0)
|
else if (strcmp(arg, "formula") == 0)
|
||||||
mc_options.dot_output |= DOT_FORMULA;
|
mc_options.dot_output |= DOT_FORMULA;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << "Unknown argument: '" << arg
|
std::cerr << "Unknown argument: '" << arg
|
||||||
<< "' for option --dot\n";
|
<< "' for option --dot\n";
|
||||||
return ARGP_ERR_UNKNOWN;
|
return ARGP_ERR_UNKNOWN;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
mc_options.is_empty = true;
|
mc_options.is_empty = true;
|
||||||
|
|
@ -154,8 +154,8 @@ static const argp_option options[] =
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct argp finput_argp = { options, parse_opt_finput,
|
const struct argp finput_argp = { options, parse_opt_finput,
|
||||||
nullptr, nullptr, nullptr,
|
nullptr, nullptr, nullptr,
|
||||||
nullptr, nullptr };
|
nullptr, nullptr };
|
||||||
|
|
||||||
const struct argp_child children[] =
|
const struct argp_child children[] =
|
||||||
{
|
{
|
||||||
|
|
@ -184,12 +184,12 @@ static int checked_main()
|
||||||
if (mc_options.selfloopize)
|
if (mc_options.selfloopize)
|
||||||
{
|
{
|
||||||
if (mc_options.dead_ap == nullptr ||
|
if (mc_options.dead_ap == nullptr ||
|
||||||
!strcasecmp(mc_options.dead_ap, "true"))
|
!strcasecmp(mc_options.dead_ap, "true"))
|
||||||
deadf = spot::formula::tt();
|
deadf = spot::formula::tt();
|
||||||
else if (!strcasecmp(mc_options.dead_ap, "false"))
|
else if (!strcasecmp(mc_options.dead_ap, "false"))
|
||||||
deadf = spot::formula::ff();
|
deadf = spot::formula::ff();
|
||||||
else
|
else
|
||||||
deadf = env.require(mc_options.dead_ap);
|
deadf = env.require(mc_options.dead_ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -197,39 +197,39 @@ static int checked_main()
|
||||||
{
|
{
|
||||||
tm.start("parsing formula");
|
tm.start("parsing formula");
|
||||||
{
|
{
|
||||||
auto pf = spot::parse_infix_psl(mc_options.formula, env, false);
|
auto pf = spot::parse_infix_psl(mc_options.formula, env, false);
|
||||||
exit_code = pf.format_errors(std::cerr);
|
exit_code = pf.format_errors(std::cerr);
|
||||||
f = pf.f;
|
f = pf.f;
|
||||||
}
|
}
|
||||||
tm.stop("parsing formula");
|
tm.stop("parsing formula");
|
||||||
|
|
||||||
tm.start("translating formula");
|
tm.start("translating formula");
|
||||||
{
|
{
|
||||||
spot::translator trans(dict);
|
spot::translator trans(dict);
|
||||||
// if (deterministic) FIXME
|
// if (deterministic) FIXME
|
||||||
// trans.set_pref(spot::postprocessor::Deterministic);
|
// trans.set_pref(spot::postprocessor::Deterministic);
|
||||||
prop = trans.run(&f);
|
prop = trans.run(&f);
|
||||||
}
|
}
|
||||||
tm.stop("translating formula");
|
tm.stop("translating formula");
|
||||||
|
|
||||||
atomic_prop_collect(f, &ap);
|
atomic_prop_collect(f, &ap);
|
||||||
|
|
||||||
if (mc_options.dot_output & DOT_FORMULA)
|
if (mc_options.dot_output & DOT_FORMULA)
|
||||||
{
|
{
|
||||||
tm.start("dot output");
|
tm.start("dot output");
|
||||||
spot::print_dot(std::cout, prop);
|
spot::print_dot(std::cout, prop);
|
||||||
tm.stop("dot output");
|
tm.stop("dot output");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mc_options.model != nullptr)
|
if (mc_options.model != nullptr)
|
||||||
{
|
{
|
||||||
tm.start("loading ltsmin model");
|
tm.start("loading ltsmin model");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
model = spot::ltsmin_model::load(mc_options.model)
|
model = spot::ltsmin_model::load(mc_options.model)
|
||||||
.kripke(&ap, dict, deadf, mc_options.compress);
|
.kripke(&ap, dict, deadf, mc_options.compress);
|
||||||
}
|
}
|
||||||
catch (std::runtime_error& e)
|
catch (std::runtime_error& e)
|
||||||
{
|
{
|
||||||
std::cerr << e.what() << '\n';
|
std::cerr << e.what() << '\n';
|
||||||
|
|
@ -237,23 +237,23 @@ static int checked_main()
|
||||||
tm.stop("loading ltsmin model");
|
tm.stop("loading ltsmin model");
|
||||||
|
|
||||||
if (!model)
|
if (!model)
|
||||||
{
|
{
|
||||||
exit_code = 2;
|
exit_code = 2;
|
||||||
goto safe_exit;
|
goto safe_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mc_options.dot_output & DOT_MODEL)
|
if (mc_options.dot_output & DOT_MODEL)
|
||||||
{
|
{
|
||||||
tm.start("dot output");
|
tm.start("dot output");
|
||||||
spot::print_dot(std::cout, model);
|
spot::print_dot(std::cout, model);
|
||||||
tm.stop("dot output");
|
tm.stop("dot output");
|
||||||
}
|
}
|
||||||
if (mc_options.kripke_output)
|
if (mc_options.kripke_output)
|
||||||
{
|
{
|
||||||
tm.start("kripke output");
|
tm.start("kripke output");
|
||||||
spot::print_hoa(std::cout, model);
|
spot::print_hoa(std::cout, model);
|
||||||
tm.stop("kripke output");
|
tm.stop("kripke output");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mc_options.formula != nullptr &&
|
if (mc_options.formula != nullptr &&
|
||||||
|
|
@ -262,92 +262,92 @@ static int checked_main()
|
||||||
product = spot::otf_product(model, prop);
|
product = spot::otf_product(model, prop);
|
||||||
|
|
||||||
if (mc_options.is_empty)
|
if (mc_options.is_empty)
|
||||||
{
|
{
|
||||||
const char* err;
|
const char* err;
|
||||||
echeck_inst = spot::make_emptiness_check_instantiator("Cou99", &err);
|
echeck_inst = spot::make_emptiness_check_instantiator("Cou99", &err);
|
||||||
if (!echeck_inst)
|
if (!echeck_inst)
|
||||||
{
|
{
|
||||||
std::cerr << "Unknown emptiness check algorihm `"
|
std::cerr << "Unknown emptiness check algorihm `"
|
||||||
<< err << "'\n";
|
<< err << "'\n";
|
||||||
exit_code = 1;
|
exit_code = 1;
|
||||||
goto safe_exit;
|
goto safe_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ec = echeck_inst->instantiate(product);
|
auto ec = echeck_inst->instantiate(product);
|
||||||
assert(ec);
|
assert(ec);
|
||||||
int memused = spot::memusage();
|
int memused = spot::memusage();
|
||||||
tm.start("running emptiness check");
|
tm.start("running emptiness check");
|
||||||
spot::emptiness_check_result_ptr res;
|
spot::emptiness_check_result_ptr res;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
res = ec->check();
|
res = ec->check();
|
||||||
}
|
}
|
||||||
catch (std::bad_alloc)
|
catch (std::bad_alloc)
|
||||||
{
|
{
|
||||||
std::cerr << "Out of memory during emptiness check."
|
std::cerr << "Out of memory during emptiness check."
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
if (!mc_options.compress)
|
if (!mc_options.compress)
|
||||||
std::cerr << "Try option -z for state compression." << std::endl;
|
std::cerr << "Try option -z for state compression." << std::endl;
|
||||||
exit_code = 2;
|
exit_code = 2;
|
||||||
exit(exit_code);
|
exit(exit_code);
|
||||||
}
|
}
|
||||||
tm.stop("running emptiness check");
|
tm.stop("running emptiness check");
|
||||||
memused = spot::memusage() - memused;
|
memused = spot::memusage() - memused;
|
||||||
|
|
||||||
ec->print_stats(std::cout);
|
ec->print_stats(std::cout);
|
||||||
std::cout << memused << " pages allocated for emptiness check"
|
std::cout << memused << " pages allocated for emptiness check"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
std::cout << "no accepting run found";
|
std::cout << "no accepting run found";
|
||||||
}
|
}
|
||||||
else if (!mc_options.compute_counterexample)
|
else if (!mc_options.compute_counterexample)
|
||||||
{
|
{
|
||||||
std::cout << "an accepting run exists "
|
std::cout << "an accepting run exists "
|
||||||
<< "(use -c to print it)" << std::endl;
|
<< "(use -c to print it)" << std::endl;
|
||||||
exit_code = 1;
|
exit_code = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
exit_code = 1;
|
exit_code = 1;
|
||||||
spot::twa_run_ptr run;
|
spot::twa_run_ptr run;
|
||||||
tm.start("computing accepting run");
|
tm.start("computing accepting run");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
run = res->accepting_run();
|
run = res->accepting_run();
|
||||||
}
|
}
|
||||||
catch (std::bad_alloc)
|
catch (std::bad_alloc)
|
||||||
{
|
{
|
||||||
std::cerr << "Out of memory while looking for counterexample."
|
std::cerr << "Out of memory while looking for counterexample."
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
exit_code = 2;
|
exit_code = 2;
|
||||||
exit(exit_code);
|
exit(exit_code);
|
||||||
}
|
}
|
||||||
tm.stop("computing accepting run");
|
tm.stop("computing accepting run");
|
||||||
|
|
||||||
if (!run)
|
if (!run)
|
||||||
{
|
{
|
||||||
std::cout << "an accepting run exists" << std::endl;
|
std::cout << "an accepting run exists" << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tm.start("reducing accepting run");
|
tm.start("reducing accepting run");
|
||||||
run = run->reduce();
|
run = run->reduce();
|
||||||
tm.stop("reducing accepting run");
|
tm.stop("reducing accepting run");
|
||||||
tm.start("printing accepting run");
|
tm.start("printing accepting run");
|
||||||
std::cout << *run;
|
std::cout << *run;
|
||||||
tm.stop("printing accepting run");
|
tm.stop("printing accepting run");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mc_options.dot_output & DOT_PRODUCT)
|
if (mc_options.dot_output & DOT_PRODUCT)
|
||||||
{
|
{
|
||||||
tm.start("dot output");
|
tm.start("dot output");
|
||||||
spot::print_dot(std::cout, product);
|
spot::print_dot(std::cout, product);
|
||||||
tm.stop("dot output");
|
tm.stop("dot output");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
safe_exit:
|
safe_exit:
|
||||||
|
|
@ -363,7 +363,7 @@ main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
setup(argv);
|
setup(argv);
|
||||||
const argp ap = { nullptr, nullptr, nullptr,
|
const argp ap = { nullptr, nullptr, nullptr,
|
||||||
argp_program_doc, children, nullptr, nullptr };
|
argp_program_doc, children, nullptr, nullptr };
|
||||||
|
|
||||||
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
|
if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr))
|
||||||
exit(err);
|
exit(err);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue