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:
Etienne Renault 2016-04-11 14:20:34 +02:00
parent 681c2b2011
commit f04074bd6d
15 changed files with 935 additions and 936 deletions

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;
} }

View file

@ -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;

View file

@ -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';

View file

@ -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;
} }
} }

View file

@ -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_;

View file

@ -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

View file

@ -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

View file

@ -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;
} }

View file

@ -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;

View file

@ -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));

View file

@ -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);