spins_kripke: rewrite, clean and document
Some parts of the kripke were confusing, lacked of documentation or could be factorized. This patch cleans all of this. * spot/ltsmin/spins_kripke.hh, spot/ltsmin/spins_kripke.hxx: here.
This commit is contained in:
parent
7aa2d292cf
commit
b9ac017382
2 changed files with 193 additions and 168 deletions
|
|
@ -33,7 +33,6 @@
|
||||||
/// to build a kripke that is thread safe
|
/// to build a kripke that is thread safe
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
||||||
/// \brief A Spins state is represented as an array of integer
|
/// \brief A Spins state is represented as an array of integer
|
||||||
/// Note that this array has two reserved slots (position 0 an 1).
|
/// Note that this array has two reserved slots (position 0 an 1).
|
||||||
///
|
///
|
||||||
|
|
@ -64,16 +63,33 @@ namespace spot
|
||||||
|
|
||||||
/// \brief The management of states (i.e. allocation/deallocation) can
|
/// \brief The management of states (i.e. allocation/deallocation) can
|
||||||
/// be painless since every time we have to consider wether the state will
|
/// be painless since every time we have to consider wether the state will
|
||||||
/// be compressed or not. This class aims to simplify this management
|
/// be compressed or not. This class aims to simplify this management.
|
||||||
class cspins_state_manager final
|
class cspins_state_manager final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// \brief Build a manager for a state of \a state_size variables
|
||||||
|
/// and indicate wether compression should be used:
|
||||||
|
/// - 1 for handle large models
|
||||||
|
/// - 2 (faster) assume all values in [0 .. 2^28-1]
|
||||||
cspins_state_manager(unsigned int state_size, int compress);
|
cspins_state_manager(unsigned int state_size, int compress);
|
||||||
|
|
||||||
|
/// \brief Get Rid of the internal representation of the state
|
||||||
int* unbox_state(cspins_state s) const;
|
int* unbox_state(cspins_state s) const;
|
||||||
// cmp is the area we can use to compute the compressed rep of dst.
|
|
||||||
cspins_state alloc_setup(int *dst, int* cmp, size_t cmpsize);
|
/// \brief Builder for a state from a raw description given in \a dst
|
||||||
|
///
|
||||||
|
/// \a cmp is the area we can use to compute the compressed
|
||||||
|
/// representatation of dst.
|
||||||
|
/// \a cmpsize the size of the previous area
|
||||||
|
cspins_state alloc_setup(int* dst, int* cmp, size_t cmpsize);
|
||||||
|
|
||||||
|
/// \brief Helper to decompress a state
|
||||||
void decompress(cspins_state s, int* uncompressed, unsigned size) const;
|
void decompress(cspins_state s, int* uncompressed, unsigned size) const;
|
||||||
|
|
||||||
|
/// \brief Help the manager to reclam the memory of a state
|
||||||
void dealloc(cspins_state s);
|
void dealloc(cspins_state s);
|
||||||
|
|
||||||
|
/// \brief The size of a state
|
||||||
unsigned int size() const;
|
unsigned int size() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -85,56 +101,67 @@ namespace spot
|
||||||
void (*fn_decompress_)(const int*, size_t, int*, size_t);
|
void (*fn_decompress_)(const int*, size_t, int*, size_t);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// \brief This structure is used as a parameter during callback when
|
||||||
// This structure is used as a parameter during callback when
|
// generating states from the shared librarie produced by LTSmin.
|
||||||
// generating states from the shared librarie produced by LTSmin
|
|
||||||
struct inner_callback_parameters
|
struct inner_callback_parameters
|
||||||
{
|
{
|
||||||
cspins_state_manager* manager; // The state manager
|
cspins_state_manager* manager; // The state manager
|
||||||
std::vector<cspins_state>* succ; // The successors of a state
|
std::vector<cspins_state>* succ; // The successors of a state
|
||||||
int* compressed_;
|
int* compressed; // Area to store compressed state
|
||||||
int* uncompressed_;
|
int* uncompressed; // Area to store uncompressed state
|
||||||
bool compress;
|
bool compress; // Should the state be compressed?
|
||||||
bool selfloopize;
|
bool selfloopize; // Should the state be selfloopized
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class provides an iterator over the successors of a state.
|
/// \brief This class provides an iterator over the successors of a state.
|
||||||
// All successors are computed once when an iterator is recycled or
|
/// All successors are computed once when an iterator is recycled or
|
||||||
// created.
|
/// created.
|
||||||
|
///
|
||||||
|
/// Note: Two threads will explore sucessors with two different orders
|
||||||
class cspins_iterator final
|
class cspins_iterator final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Inner struct used to pack the various arguments required by the iterator
|
||||||
|
struct cspins_iterator_param
|
||||||
|
{
|
||||||
|
cspins_state s;
|
||||||
|
const spot::spins_interface* d;
|
||||||
|
cspins_state_manager& manager;
|
||||||
|
inner_callback_parameters& inner;
|
||||||
|
cube cond;
|
||||||
|
bool compress;
|
||||||
|
bool selfloopize;
|
||||||
|
spot::cubeset& cubeset;
|
||||||
|
int dead_idx;
|
||||||
|
unsigned tid;
|
||||||
|
};
|
||||||
|
|
||||||
cspins_iterator(const cspins_iterator&) = delete;
|
cspins_iterator(const cspins_iterator&) = delete;
|
||||||
cspins_iterator(cspins_iterator&) = delete;
|
cspins_iterator(cspins_iterator&) = delete;
|
||||||
cspins_iterator(cspins_state s,
|
|
||||||
const spot::spins_interface* d,
|
|
||||||
cspins_state_manager& manager,
|
|
||||||
inner_callback_parameters& inner,
|
|
||||||
cube cond,
|
|
||||||
bool compress,
|
|
||||||
bool selfloopize,
|
|
||||||
cubeset& cubeset,
|
|
||||||
int dead_idx, unsigned tid);
|
|
||||||
|
|
||||||
void recycle(cspins_state s,
|
|
||||||
const spot::spins_interface* d,
|
|
||||||
cspins_state_manager& manager,
|
|
||||||
inner_callback_parameters& inner,
|
|
||||||
cube cond,
|
|
||||||
bool compress,
|
|
||||||
bool selfloopize,
|
|
||||||
cubeset& cubeset, int dead_idx, unsigned tid);
|
|
||||||
|
|
||||||
|
cspins_iterator(cspins_iterator_param& p);
|
||||||
|
void recycle(cspins_iterator_param& p);
|
||||||
~cspins_iterator();
|
~cspins_iterator();
|
||||||
|
|
||||||
void next();
|
void next();
|
||||||
bool done() const;
|
bool done() const;
|
||||||
cspins_state state() const;
|
cspins_state state() const;
|
||||||
cube condition() const;
|
cube condition() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Compute the real index in the successor vector
|
/// \brief Compute the real index in the successor vector
|
||||||
unsigned compute_index() const;
|
unsigned compute_index() const;
|
||||||
|
|
||||||
|
inline void setup_iterator(cspins_state s,
|
||||||
|
const spot::spins_interface* d,
|
||||||
|
cspins_state_manager& manager,
|
||||||
|
inner_callback_parameters& inner,
|
||||||
|
cube& cond,
|
||||||
|
bool compress,
|
||||||
|
bool selfloopize,
|
||||||
|
cubeset& cubeset,
|
||||||
|
int dead_idx);
|
||||||
|
|
||||||
std::vector<cspins_state> successors_;
|
std::vector<cspins_state> successors_;
|
||||||
unsigned int current_;
|
unsigned int current_;
|
||||||
cube cond_;
|
cube cond_;
|
||||||
|
|
@ -146,20 +173,36 @@ namespace spot
|
||||||
template<>
|
template<>
|
||||||
class kripkecube<cspins_state, cspins_iterator> final
|
class kripkecube<cspins_state, cspins_iterator> final
|
||||||
{
|
{
|
||||||
|
// Define operators that are available for atomic proposition
|
||||||
typedef enum {
|
enum class relop
|
||||||
OP_EQ_VAR, OP_NE_VAR, OP_LT_VAR, OP_GT_VAR, OP_LE_VAR, OP_GE_VAR,
|
{
|
||||||
VAR_OP_EQ, VAR_OP_NE, VAR_OP_LT, VAR_OP_GT, VAR_OP_LE, VAR_OP_GE,
|
OP_EQ_VAR, // 1 == a
|
||||||
VAR_OP_EQ_VAR, VAR_OP_NE_VAR, VAR_OP_LT_VAR,
|
OP_NE_VAR, // 1 != a
|
||||||
VAR_OP_GT_VAR, VAR_OP_LE_VAR, VAR_OP_GE_VAR, VAR_DEAD
|
OP_LT_VAR, // 1 < a
|
||||||
} relop;
|
OP_GT_VAR, // 1 > a
|
||||||
|
OP_LE_VAR, // 1 <= a
|
||||||
|
OP_GE_VAR, // 1 >= a
|
||||||
|
VAR_OP_EQ, // a == 1
|
||||||
|
VAR_OP_NE, // a != 1
|
||||||
|
VAR_OP_LT, // a < 1
|
||||||
|
VAR_OP_GT, // a >= 1
|
||||||
|
VAR_OP_LE, // a <= 1
|
||||||
|
VAR_OP_GE, // a >= 1
|
||||||
|
VAR_OP_EQ_VAR, // a == b
|
||||||
|
VAR_OP_NE_VAR, // a != b
|
||||||
|
VAR_OP_LT_VAR, // a < b
|
||||||
|
VAR_OP_GT_VAR, // a > b
|
||||||
|
VAR_OP_LE_VAR, // a <= b
|
||||||
|
VAR_OP_GE_VAR, // a >= b
|
||||||
|
VAR_DEAD // The atomic proposition used to label deadlock
|
||||||
|
};
|
||||||
|
|
||||||
// Structure for complex atomic proposition
|
// Structure for complex atomic proposition
|
||||||
struct one_prop
|
struct one_prop
|
||||||
{
|
{
|
||||||
int lval;
|
int lval; // Index of left variable or raw number
|
||||||
relop op;
|
relop op; // The operator
|
||||||
int rval;
|
int rval; // Index or right variable or raw number
|
||||||
};
|
};
|
||||||
|
|
||||||
// Data structure to store complex atomic propositions
|
// Data structure to store complex atomic propositions
|
||||||
|
|
@ -176,29 +219,36 @@ namespace spot
|
||||||
std::string to_string(const cspins_state s, unsigned tid = 0) const;
|
std::string to_string(const cspins_state s, unsigned tid = 0) const;
|
||||||
cspins_iterator* succ(const cspins_state s, unsigned tid);
|
cspins_iterator* succ(const cspins_state s, unsigned tid);
|
||||||
void recycle(cspins_iterator* it, unsigned tid);
|
void recycle(cspins_iterator* it, unsigned tid);
|
||||||
|
|
||||||
|
/// \brief List the atomic propositions used by *this* kripke
|
||||||
const std::vector<std::string> get_ap();
|
const std::vector<std::string> get_ap();
|
||||||
|
|
||||||
|
/// \brief The number of thread used by *this* kripke
|
||||||
unsigned get_threads();
|
unsigned get_threads();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Parse the set of atomic proposition to have a more
|
/// \brief Parse the set of atomic proposition to have a more
|
||||||
/// efficient data strucure for computation
|
/// efficient data strucure for computation
|
||||||
void match_aps(std::vector<std::string>& aps, std::string dead_prop);
|
void match_aps(std::vector<std::string>& aps, std::string dead_prop);
|
||||||
|
|
||||||
/// Compute the cube associated to each state. The cube
|
/// \brief Compute the cube associated to each state. The cube
|
||||||
/// will then be given to all iterators.
|
/// will then be given to all iterators.
|
||||||
void compute_condition(cube c, cspins_state s, unsigned tid = 0);
|
void compute_condition(cube c, cspins_state s, unsigned tid = 0);
|
||||||
|
|
||||||
spins_interface_ptr sip_;
|
spins_interface_ptr sip_; // The interface to the shared library
|
||||||
const spot::spins_interface* d_; // To avoid numerous sip_.get()
|
const spot::spins_interface* d_; // To avoid numerous sip_.get()
|
||||||
cspins_state_manager* manager_;
|
cspins_state_manager* manager_; // One manager per thread
|
||||||
bool compress_;
|
bool compress_; // Should a compression be performed
|
||||||
|
|
||||||
|
// One per threads to store no longer used iterators (and save memory)
|
||||||
std::vector<std::vector<cspins_iterator*>> recycle_;
|
std::vector<std::vector<cspins_iterator*>> recycle_;
|
||||||
inner_callback_parameters* inner_;
|
|
||||||
cubeset cubeset_;
|
inner_callback_parameters* inner_; // One callback per thread
|
||||||
bool selfloopize_;
|
cubeset cubeset_; // A single cubeset to manipulate cubes
|
||||||
int dead_idx_;
|
bool selfloopize_; // Should selfloopize be performed
|
||||||
std::vector<std::string> aps_;
|
int dead_idx_; // If yes, index of the "dead ap"
|
||||||
unsigned int nb_threads_;
|
std::vector<std::string> aps_; // All the atomic propositions
|
||||||
|
unsigned int nb_threads_; // The number of threads used
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief shortcut to manipulate the kripke below
|
/// \brief shortcut to manipulate the kripke below
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// -*- coding: utf-8 -*-
|
// -*- coding: utf-8 -*-
|
||||||
// Copyright (C) 2017 Laboratoire de Recherche et Développement de
|
// Copyright (C) 2017, 2018 Laboratoire de Recherche et Développement de
|
||||||
// l'Epita (LRDE)
|
// l'Epita (LRDE)
|
||||||
//
|
//
|
||||||
// This file is part of Spot, a model checking library.
|
// This file is part of Spot, a model checking library.
|
||||||
|
|
@ -95,22 +95,35 @@ namespace spot
|
||||||
return state_size_;
|
return state_size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cspins_iterator::cspins_iterator(cspins_iterator_param& p)
|
||||||
// This class provides an iterator over the successors of a state.
|
: current_(0), cond_(p.cond), tid_(p.tid)
|
||||||
// All successors are computed once when an iterator is recycled or
|
|
||||||
// created.
|
|
||||||
cspins_iterator::cspins_iterator(cspins_state s,
|
|
||||||
const spot::spins_interface* d,
|
|
||||||
cspins_state_manager& manager,
|
|
||||||
inner_callback_parameters& inner,
|
|
||||||
cube cond,
|
|
||||||
bool compress,
|
|
||||||
bool selfloopize,
|
|
||||||
cubeset& cubeset,
|
|
||||||
int dead_idx, unsigned tid)
|
|
||||||
: current_(0), cond_(cond), tid_(tid)
|
|
||||||
{
|
{
|
||||||
successors_.reserve(10);
|
successors_.reserve(10);
|
||||||
|
setup_iterator(p.s, p.d, p.manager, p.inner, p.cond, p.compress,
|
||||||
|
p.selfloopize, p.cubeset, p.dead_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cspins_iterator::recycle(cspins_iterator_param& p)
|
||||||
|
{
|
||||||
|
tid_ = p.tid;
|
||||||
|
cond_ = p.cond;
|
||||||
|
current_ = 0;
|
||||||
|
// Constant time since int* is is_trivially_destructible
|
||||||
|
successors_.clear();
|
||||||
|
setup_iterator(p.s, p.d, p.manager, p.inner, p.cond, p.compress,
|
||||||
|
p.selfloopize, p.cubeset, p.dead_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cspins_iterator::setup_iterator(cspins_state s,
|
||||||
|
const spot::spins_interface* d,
|
||||||
|
cspins_state_manager& manager,
|
||||||
|
inner_callback_parameters& inner,
|
||||||
|
cube& cond,
|
||||||
|
bool compress,
|
||||||
|
bool selfloopize,
|
||||||
|
cubeset& cubeset,
|
||||||
|
int dead_idx)
|
||||||
|
{
|
||||||
inner.manager = &manager;
|
inner.manager = &manager;
|
||||||
inner.succ = &successors_;
|
inner.succ = &successors_;
|
||||||
inner.compress = compress;
|
inner.compress = compress;
|
||||||
|
|
@ -119,7 +132,7 @@ namespace spot
|
||||||
|
|
||||||
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),
|
||||||
|
|
@ -127,7 +140,7 @@ namespace spot
|
||||||
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);
|
||||||
inner->succ->push_back(s);
|
inner->succ->push_back(s);
|
||||||
},
|
},
|
||||||
|
|
@ -138,49 +151,7 @@ namespace spot
|
||||||
if (dead_idx != -1)
|
if (dead_idx != -1)
|
||||||
cubeset.set_true_var(cond, dead_idx);
|
cubeset.set_true_var(cond, dead_idx);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void cspins_iterator::recycle(cspins_state s,
|
|
||||||
const spot::spins_interface* d,
|
|
||||||
cspins_state_manager& manager,
|
|
||||||
inner_callback_parameters& inner,
|
|
||||||
cube cond,
|
|
||||||
bool compress,
|
|
||||||
bool selfloopize,
|
|
||||||
cubeset& cubeset, int dead_idx, unsigned tid)
|
|
||||||
{
|
|
||||||
tid_ = tid;
|
|
||||||
cond_ = cond;
|
|
||||||
current_ = 0;
|
|
||||||
// Constant time since int* is is_trivially_destructible
|
|
||||||
successors_.clear();
|
|
||||||
inner.manager = &manager;
|
|
||||||
inner.succ = &successors_;
|
|
||||||
inner.compress = compress;
|
|
||||||
inner.selfloopize = selfloopize;
|
|
||||||
int* ref = s;
|
|
||||||
|
|
||||||
if (compress)
|
|
||||||
// Already filled by compute_condition
|
|
||||||
ref = inner.uncompressed_;
|
|
||||||
|
|
||||||
int n = d->get_successors
|
|
||||||
(nullptr, manager.unbox_state(ref),
|
|
||||||
[](void* arg, transition_info_t*, int *dst){
|
|
||||||
inner_callback_parameters* inner =
|
|
||||||
static_cast<inner_callback_parameters*>(arg);
|
|
||||||
cspins_state s =
|
|
||||||
inner->manager->alloc_setup(dst, inner->compressed_,
|
|
||||||
inner->manager->size() * 2);
|
|
||||||
inner->succ->push_back(s);
|
|
||||||
},
|
|
||||||
&inner);
|
|
||||||
if (!n && selfloopize)
|
|
||||||
{
|
|
||||||
successors_.push_back(s);
|
|
||||||
if (dead_idx != -1)
|
|
||||||
cubeset.set_true_var(cond, dead_idx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cspins_iterator::~cspins_iterator()
|
cspins_iterator::~cspins_iterator()
|
||||||
|
|
@ -240,8 +211,8 @@ namespace spot
|
||||||
recycle_.back().reserve(2000000);
|
recycle_.back().reserve(2000000);
|
||||||
new (&manager_[i])
|
new (&manager_[i])
|
||||||
cspins_state_manager(d_->get_state_size(), compress);
|
cspins_state_manager(d_->get_state_size(), compress);
|
||||||
inner_[i].compressed_ = new int[d_->get_state_size() * 2];
|
inner_[i].compressed = new int[d_->get_state_size() * 2];
|
||||||
inner_[i].uncompressed_ = new int[d_->get_state_size()+30];
|
inner_[i].uncompressed = new int[d_->get_state_size()+30];
|
||||||
}
|
}
|
||||||
dead_idx_ = -1;
|
dead_idx_ = -1;
|
||||||
match_aps(visible_aps, dead_prop);
|
match_aps(visible_aps, dead_prop);
|
||||||
|
|
@ -262,8 +233,8 @@ namespace spot
|
||||||
for (unsigned i = 0; i < nb_threads_; ++i)
|
for (unsigned i = 0; i < nb_threads_; ++i)
|
||||||
{
|
{
|
||||||
manager_[i].~cspins_state_manager();
|
manager_[i].~cspins_state_manager();
|
||||||
delete[] inner_[i].compressed_;
|
delete[] inner_[i].compressed;
|
||||||
delete[] inner_[i].uncompressed_;
|
delete[] inner_[i].uncompressed;
|
||||||
}
|
}
|
||||||
::operator delete(manager_);
|
::operator delete(manager_);
|
||||||
delete[] inner_;
|
delete[] inner_;
|
||||||
|
|
@ -271,9 +242,9 @@ namespace spot
|
||||||
|
|
||||||
cspins_state kripkecube<cspins_state, cspins_iterator>::initial(unsigned tid)
|
cspins_state kripkecube<cspins_state, cspins_iterator>::initial(unsigned tid)
|
||||||
{
|
{
|
||||||
d_->get_initial_state(inner_[tid].uncompressed_);
|
d_->get_initial_state(inner_[tid].uncompressed);
|
||||||
return manager_[tid].alloc_setup(inner_[tid].uncompressed_,
|
return manager_[tid].alloc_setup(inner_[tid].uncompressed,
|
||||||
inner_[tid].compressed_,
|
inner_[tid].compressed,
|
||||||
manager_[tid].size() * 2);
|
manager_[tid].size() * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,9 +257,9 @@ namespace spot
|
||||||
cspins_state ref = out;
|
cspins_state ref = out;
|
||||||
if (compress_)
|
if (compress_)
|
||||||
{
|
{
|
||||||
manager_[tid].decompress(s, inner_[tid].uncompressed_,
|
manager_[tid].decompress(s, inner_[tid].uncompressed,
|
||||||
manager_[tid].size());
|
manager_[tid].size());
|
||||||
ref = inner_[tid].uncompressed_;
|
ref = inner_[tid].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)) +
|
||||||
|
|
@ -301,21 +272,26 @@ namespace spot
|
||||||
kripkecube<cspins_state, cspins_iterator>::succ(const cspins_state s,
|
kripkecube<cspins_state, cspins_iterator>::succ(const cspins_state s,
|
||||||
unsigned tid)
|
unsigned tid)
|
||||||
{
|
{
|
||||||
|
cspins_iterator::cspins_iterator_param p =
|
||||||
|
{
|
||||||
|
s, d_, manager_[tid], inner_[tid],
|
||||||
|
nullptr, compress_, selfloopize_,
|
||||||
|
cubeset_, dead_idx_, tid
|
||||||
|
};
|
||||||
|
|
||||||
if (SPOT_LIKELY(!recycle_[tid].empty()))
|
if (SPOT_LIKELY(!recycle_[tid].empty()))
|
||||||
{
|
{
|
||||||
auto tmp = recycle_[tid].back();
|
auto tmp = recycle_[tid].back();
|
||||||
recycle_[tid].pop_back();
|
recycle_[tid].pop_back();
|
||||||
compute_condition(tmp->condition(), s, tid);
|
p.cond = tmp->condition();
|
||||||
tmp->recycle(s, d_, manager_[tid], inner_[tid],
|
compute_condition(p.cond, s, tid);
|
||||||
tmp->condition(), compress_, selfloopize_,
|
tmp->recycle(p);
|
||||||
cubeset_, dead_idx_, tid);
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
cube cond = cubeset_.alloc();
|
cube cond = cubeset_.alloc();
|
||||||
|
p.cond = cond;
|
||||||
compute_condition(cond, s, tid);
|
compute_condition(cond, s, tid);
|
||||||
return new cspins_iterator(s, d_, manager_[tid], inner_[tid],
|
return new cspins_iterator(p);
|
||||||
cond, compress_, selfloopize_,
|
|
||||||
cubeset_, dead_idx_, tid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -346,9 +322,9 @@ namespace spot
|
||||||
// State is compressed, uncompress it
|
// State is compressed, uncompress it
|
||||||
if (compress_)
|
if (compress_)
|
||||||
{
|
{
|
||||||
manager_[tid].decompress(s, inner_[tid].uncompressed_+2,
|
manager_[tid].decompress(s, inner_[tid].uncompressed+2,
|
||||||
manager_[tid].size());
|
manager_[tid].size());
|
||||||
vars = inner_[tid].uncompressed_ + 2;
|
vars = inner_[tid].uncompressed + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& ap: pset_)
|
for (auto& ap: pset_)
|
||||||
|
|
@ -357,61 +333,61 @@ namespace spot
|
||||||
bool cond = false;
|
bool cond = false;
|
||||||
switch (ap.op)
|
switch (ap.op)
|
||||||
{
|
{
|
||||||
case OP_EQ_VAR:
|
case relop::OP_EQ_VAR:
|
||||||
cond = (ap.lval == vars[ap.rval]);
|
cond = (ap.lval == vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case OP_NE_VAR:
|
case relop::OP_NE_VAR:
|
||||||
cond = (ap.lval != vars[ap.rval]);
|
cond = (ap.lval != vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case OP_LT_VAR:
|
case relop::OP_LT_VAR:
|
||||||
cond = (ap.lval < vars[ap.rval]);
|
cond = (ap.lval < vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case OP_GT_VAR:
|
case relop::OP_GT_VAR:
|
||||||
cond = (ap.lval > vars[ap.rval]);
|
cond = (ap.lval > vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case OP_LE_VAR:
|
case relop::OP_LE_VAR:
|
||||||
cond = (ap.lval <= vars[ap.rval]);
|
cond = (ap.lval <= vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case OP_GE_VAR:
|
case relop::OP_GE_VAR:
|
||||||
cond = (ap.lval >= vars[ap.rval]);
|
cond = (ap.lval >= vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_EQ:
|
case relop::VAR_OP_EQ:
|
||||||
cond = (vars[ap.lval] == ap.rval);
|
cond = (vars[ap.lval] == ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_NE:
|
case relop::VAR_OP_NE:
|
||||||
cond = (vars[ap.lval] != ap.rval);
|
cond = (vars[ap.lval] != ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_LT:
|
case relop::VAR_OP_LT:
|
||||||
cond = (vars[ap.lval] < ap.rval);
|
cond = (vars[ap.lval] < ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_GT:
|
case relop::VAR_OP_GT:
|
||||||
cond = (vars[ap.lval] > ap.rval);
|
cond = (vars[ap.lval] > ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_LE:
|
case relop::VAR_OP_LE:
|
||||||
cond = (vars[ap.lval] <= ap.rval);
|
cond = (vars[ap.lval] <= ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_GE:
|
case relop::VAR_OP_GE:
|
||||||
cond = (vars[ap.lval] >= ap.rval);
|
cond = (vars[ap.lval] >= ap.rval);
|
||||||
break;
|
break;
|
||||||
case VAR_OP_EQ_VAR:
|
case relop::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 relop::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 relop::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 relop::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 relop::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 relop::VAR_OP_GE_VAR:
|
||||||
cond = (vars[ap.lval] >= vars[ap.rval]);
|
cond = (vars[ap.lval] >= vars[ap.rval]);
|
||||||
break;
|
break;
|
||||||
case VAR_DEAD:
|
case relop::VAR_DEAD:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
SPOT_ASSERT(false);
|
SPOT_ASSERT(false);
|
||||||
|
|
@ -465,7 +441,7 @@ namespace spot
|
||||||
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 , relop::VAR_DEAD, 0});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -483,7 +459,7 @@ namespace spot
|
||||||
// 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});
|
relop::VAR_OP_NE, 0});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -534,7 +510,6 @@ namespace spot
|
||||||
// And finally the operator
|
// And finally the operator
|
||||||
relop oper;
|
relop oper;
|
||||||
|
|
||||||
|
|
||||||
// Now, left and (possibly) right may refer atomic
|
// Now, left and (possibly) right may 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
|
||||||
|
|
@ -586,7 +561,7 @@ namespace spot
|
||||||
(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});
|
relop::VAR_OP_EQ, ei->second});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -631,7 +606,7 @@ namespace spot
|
||||||
(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});
|
relop::VAR_OP_EQ, ei->second});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -711,7 +686,7 @@ namespace spot
|
||||||
(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});
|
relop::VAR_OP_EQ, ei->second});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -729,23 +704,23 @@ namespace spot
|
||||||
|
|
||||||
// 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? relop::VAR_OP_EQ_VAR :
|
||||||
(left_is_digit? OP_EQ_VAR : VAR_OP_EQ);
|
(left_is_digit? relop::OP_EQ_VAR : relop::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? relop::VAR_OP_NE_VAR :
|
||||||
(left_is_digit? OP_NE_VAR : VAR_OP_NE);
|
(left_is_digit? relop::OP_NE_VAR : relop::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? relop::VAR_OP_LT_VAR :
|
||||||
(left_is_digit? OP_LT_VAR : VAR_OP_LT);
|
(left_is_digit? relop::OP_LT_VAR : relop::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? relop::VAR_OP_GT_VAR :
|
||||||
(left_is_digit? OP_GT_VAR : VAR_OP_GT);
|
(left_is_digit? relop::OP_GT_VAR : relop::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? relop::VAR_OP_LE_VAR :
|
||||||
(left_is_digit? OP_LE_VAR : VAR_OP_LE);
|
(left_is_digit? relop::OP_LE_VAR : relop::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? relop::VAR_OP_GE_VAR :
|
||||||
(left_is_digit? OP_GE_VAR : VAR_OP_GE);
|
(left_is_digit? relop::OP_GE_VAR : relop::VAR_OP_GE);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err << "\nOperation \"" << op
|
err << "\nOperation \"" << op
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue