Reformatting

This commit is contained in:
Artur Meski
2018-03-28 21:00:44 +01:00
parent c90a87875a
commit 5f1a759c8f
18 changed files with 2204 additions and 2056 deletions

View File

@@ -1,11 +1,11 @@
#ifndef __BDD_MACRO_HH__ #ifndef __BDD_MACRO_HH__
#define __BDD_MACRO_HH__ #define __BDD_MACRO_HH__
#define BDD_IFF(p,q) (!(p+q)+(p*q)) #define BDD_IFF(p,q) (!(p+q)+(p*q))
#define BDD_TRUE (cuddMgr->bddOne()) #define BDD_TRUE (cuddMgr->bddOne())
#define BDD_FALSE (cuddMgr->bddZero()) #define BDD_FALSE (cuddMgr->bddZero())
#define BDD_PRINT(t) ((t).PrintMinterm()) #define BDD_PRINT(t) ((t).PrintMinterm())
#endif #endif

View File

@@ -3,106 +3,109 @@
CtxAut::CtxAut(Options *opts, RctSys *parent_rctsys) CtxAut::CtxAut(Options *opts, RctSys *parent_rctsys)
{ {
setOptions(opts); setOptions(opts);
this->parent_rctsys = parent_rctsys; this->parent_rctsys = parent_rctsys;
} }
bool CtxAut::hasState(std::string name) bool CtxAut::hasState(std::string name)
{ {
if (states_names.find(name) == states_names.end()) if (states_names.find(name) == states_names.end()) {
return false; return false;
else }
return true; else {
return true;
}
} }
State CtxAut::getStateID(std::string name) State CtxAut::getStateID(std::string name)
{ {
if (!hasState(name)) if (!hasState(name)) {
{ FERROR("No such state: " << name);
FERROR("No such state: " << name); }
}
return states_names[name]; return states_names[name];
} }
std::string CtxAut::getStateName(State state_id) std::string CtxAut::getStateName(State state_id)
{ {
assert(state_id < states_ids.size()); assert(state_id < states_ids.size());
return states_ids[state_id]; return states_ids[state_id];
} }
void CtxAut::addState(std::string name) void CtxAut::addState(std::string name)
{ {
if (!hasState(name)) if (!hasState(name)) {
{ State new_state_id = states_ids.size();
State new_state_id = states_ids.size();
VERB_L2("Adding state: " << name << " index=" << new_state_id); VERB_L2("Adding state: " << name << " index=" << new_state_id);
states_ids.push_back(name); states_ids.push_back(name);
states_names[name] = new_state_id; states_names[name] = new_state_id;
if (!init_state_defined) if (!init_state_defined) {
{ setInitState(name);
setInitState(name);
}
} }
}
} }
void CtxAut::setInitState(std::string name) void CtxAut::setInitState(std::string name)
{ {
VERB_L2("Setting initial CA state: " << name); VERB_L2("Setting initial CA state: " << name);
State state_id = getStateID(name); State state_id = getStateID(name);
VERB_L2("Got initial CA state ID: index=" << state_id); VERB_L2("Got initial CA state ID: index=" << state_id);
init_state_id = state_id; init_state_id = state_id;
init_state_defined = true; init_state_defined = true;
} }
State CtxAut::getInitState(void) State CtxAut::getInitState(void)
{ {
assert(init_state_defined); assert(init_state_defined);
return init_state_id; return init_state_id;
} }
void CtxAut::printAutomaton(void) void CtxAut::printAutomaton(void)
{ {
showStates(); showStates();
showTransitions(); showTransitions();
} }
void CtxAut::showStates(void) void CtxAut::showStates(void)
{ {
cout << "# Context Automaton States:" << endl; cout << "# Context Automaton States:" << endl;
cout << " = Init state: " << getStateName(init_state_id) << endl; cout << " = Init state: " << getStateName(init_state_id) << endl;
for (const auto &s : states_ids)
cout << " * " << s << endl; for (const auto &s : states_ids) {
cout << " * " << s << endl;
}
} }
void CtxAut::pushContextEntity(Entity entity_id) void CtxAut::pushContextEntity(Entity entity_id)
{ {
tmpEntities.insert(entity_id); tmpEntities.insert(entity_id);
} }
void CtxAut::addTransition(std::string srcStateName, std::string dstStateName) void CtxAut::addTransition(std::string srcStateName, std::string dstStateName)
{ {
VERB_L3("Saving transition"); VERB_L3("Saving transition");
CtxAutTransition new_transition; CtxAutTransition new_transition;
new_transition.src_state = getStateID(srcStateName); new_transition.src_state = getStateID(srcStateName);
new_transition.ctx = tmpEntities; new_transition.ctx = tmpEntities;
tmpEntities.clear(); tmpEntities.clear();
new_transition.dst_state = getStateID(dstStateName); new_transition.dst_state = getStateID(dstStateName);
transitions.push_back(new_transition); transitions.push_back(new_transition);
} }
void CtxAut::showTransitions(void) void CtxAut::showTransitions(void)
{ {
cout << "# Context Automaton Transitions:" << endl; cout << "# Context Automaton Transitions:" << endl;
for (const auto &t : transitions)
{ for (const auto &t : transitions) {
cout << " * [" << getStateName(t.src_state) << " -> " << getStateName(t.dst_state) cout << " * [" << getStateName(t.src_state) << " -> " << getStateName(
<< "]: {" << parent_rctsys->entitiesToStr(t.ctx) << "}" << endl; t.dst_state)
} << "]: {" << parent_rctsys->entitiesToStr(t.ctx) << "}" << endl;
}
} }
/** EOF **/ /** EOF **/

View File

@@ -29,31 +29,37 @@ class CtxAut
{ {
friend class SymRS; friend class SymRS;
public: public:
CtxAut(Options *opts, RctSys *parent_rctsys); CtxAut(Options *opts, RctSys *parent_rctsys);
bool hasState(std::string name); bool hasState(std::string name);
void addState(std::string stateName); void addState(std::string stateName);
void setInitState(std::string stateName); void setInitState(std::string stateName);
State getInitState(void); State getInitState(void);
State getStateID(std::string name); State getStateID(std::string name);
std::string getStateName(State state_id); std::string getStateName(State state_id);
void printAutomaton(void); void printAutomaton(void);
void showStates(void); void showStates(void);
void addTransition(std::string srcStateName, std::string dstStateName); void addTransition(std::string srcStateName, std::string dstStateName);
void showTransitions(void); void showTransitions(void);
void pushContextEntity(Entity entity_id); void pushContextEntity(Entity entity_id);
void setOptions(Options *opts) { this->opts = opts; } void setOptions(Options *opts)
size_t statesCount(void) { return states_ids.size(); } {
this->opts = opts;
}
size_t statesCount(void)
{
return states_ids.size();
}
private: private:
RctSys *parent_rctsys; RctSys *parent_rctsys;
Options *opts; Options *opts;
StatesById states_ids; StatesById states_ids;
StatesByName states_names; StatesByName states_names;
State init_state_id; State init_state_id;
bool init_state_defined; bool init_state_defined;
Entities tmpEntities; Entities tmpEntities;
CtxAutTransitions transitions; CtxAutTransitions transitions;
}; };
#endif /* RS_CTX_AUT_HH */ #endif /* RS_CTX_AUT_HH */

View File

@@ -11,313 +11,300 @@
std::string BoolContexts::toStr(void) const std::string BoolContexts::toStr(void) const
{ {
if (oper == BCTX_PV) if (oper == BCTX_PV) {
{ return name;
return name; }
else if (oper == BCTX_TF) {
if (tf) {
return "true";
} }
else if (oper == BCTX_TF) else {
{ return "false";
if (tf) return "true";
else return "false";
}
else if (oper == BCTX_AND)
{
return "(" + arg[0]->toStr() + " AND " + arg[1]->toStr() + ")";
}
else if (oper == BCTX_OR)
{
return "(" + arg[0]->toStr() + " OR " + arg[1]->toStr() + ")";
}
else if (oper == BCTX_XOR)
{
return "(" + arg[0]->toStr() + " XOR " + arg[1]->toStr() + ")";
}
else if (oper == BCTX_NOT)
{
return "~" + arg[0]->toStr();
} }
}
else if (oper == BCTX_AND) {
return "(" + arg[0]->toStr() + " AND " + arg[1]->toStr() + ")";
}
else if (oper == BCTX_OR) {
return "(" + arg[0]->toStr() + " OR " + arg[1]->toStr() + ")";
}
else if (oper == BCTX_XOR) {
return "(" + arg[0]->toStr() + " XOR " + arg[1]->toStr() + ")";
}
else if (oper == BCTX_NOT) {
return "~" + arg[0]->toStr();
}
else else {
{ return "??";
return "??"; assert(0);
assert(0); }
}
} }
BDD BoolContexts::getBDD(const SymRS *srs) const BDD BoolContexts::getBDD(const SymRS *srs) const
{ {
if (oper == BCTX_PV) if (oper == BCTX_PV) {
{ return srs->encActStrEntity(name);
return srs->encActStrEntity(name); }
} else if (oper == BCTX_TF) {
else if (oper == BCTX_TF) if (tf) {
{ return srs->getBDDtrue();
if (tf) return srs->getBDDtrue(); }
else return srs->getBDDfalse(); else {
} return srs->getBDDfalse();
else if (oper == BCTX_AND) }
{ }
return arg[0]->getBDD(srs) * arg[1]->getBDD(srs); else if (oper == BCTX_AND) {
} return arg[0]->getBDD(srs) * arg[1]->getBDD(srs);
else if (oper == BCTX_OR) }
{ else if (oper == BCTX_OR) {
return arg[0]->getBDD(srs) + arg[1]->getBDD(srs); return arg[0]->getBDD(srs) + arg[1]->getBDD(srs);
} }
else if (oper == BCTX_XOR) else if (oper == BCTX_XOR) {
{ return arg[0]->getBDD(srs) ^ arg[1]->getBDD(srs);
return arg[0]->getBDD(srs) ^ arg[1]->getBDD(srs); }
} else if (oper == BCTX_NOT) {
else if (oper == BCTX_NOT) return !arg[0]->getBDD(srs);
{ }
return !arg[0]->getBDD(srs); else {
} assert(0);
else FERROR("Undefined operator used in Boolean context definition. This should not happen.");
{ return srs->getBDDfalse();
assert(0); }
FERROR("Undefined operator used in Boolean context definition. This should not happen.");
return srs->getBDDfalse();
}
} }
std::string FormRSCTL::toStr(void) const std::string FormRSCTL::toStr(void) const
{ {
if (oper == RSCTL_PV) if (oper == RSCTL_PV) {
{ return name;
return name; }
else if (oper == RSCTL_TF) {
if (tf) {
return "true";
} }
else if (oper == RSCTL_TF) else {
{ return "false";
if (tf) return "true";
else return "false";
}
else if (oper == RSCTL_AND)
{
return "(" + arg[0]->toStr() + " AND " + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_OR)
{
return "(" + arg[0]->toStr() + " OR " + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_XOR)
{
return "(" + arg[0]->toStr() + " XOR " + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_IMPL)
{
return "(" + arg[0]->toStr() + " IMPLIES " + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_NOT)
{
return "~" + arg[0]->toStr();
}
else if (oper == RSCTL_EX)
{
return "EX(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_EG)
{
return "EG(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_EU)
{
return "EU(" + arg[0]->toStr() + "," + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_EF)
{
return "EF(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AX)
{
return "AX(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AG)
{
return "AG(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AU)
{
return "AU(" + arg[0]->toStr() + "," + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_AF)
{
return "AF(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_EX_ACT)
{
return "E" + getActionsStr() + "X(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_EG_ACT)
{
return "E" + getActionsStr() + "G(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_EU_ACT)
{
return "E" + getActionsStr() + "U(" + arg[0]->toStr() + "," + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_EF_ACT)
{
return "E" + getActionsStr() + "F(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AX_ACT)
{
return "A" + getActionsStr() + "X(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AG_ACT)
{
return "A" + getActionsStr() + "G(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AU_ACT)
{
return "A" + getActionsStr() + "U(" + arg[0]->toStr() + "," + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_AF_ACT)
{
return "A" + getActionsStr() + "F(" + arg[0]->toStr() + ")";
} }
}
else if (oper == RSCTL_AND) {
return "(" + arg[0]->toStr() + " AND " + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_OR) {
return "(" + arg[0]->toStr() + " OR " + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_XOR) {
return "(" + arg[0]->toStr() + " XOR " + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_IMPL) {
return "(" + arg[0]->toStr() + " IMPLIES " + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_NOT) {
return "~" + arg[0]->toStr();
}
else if (oper == RSCTL_EX) {
return "EX(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_EG) {
return "EG(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_EU) {
return "EU(" + arg[0]->toStr() + "," + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_EF) {
return "EF(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AX) {
return "AX(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AG) {
return "AG(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AU) {
return "AU(" + arg[0]->toStr() + "," + arg[1]->toStr() + ")";
}
else if (oper == RSCTL_AF) {
return "AF(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_EX_ACT) {
return "E" + getActionsStr() + "X(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_EG_ACT) {
return "E" + getActionsStr() + "G(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_EU_ACT) {
return "E" + getActionsStr() + "U(" + arg[0]->toStr() + "," + arg[1]->toStr()
+ ")";
}
else if (oper == RSCTL_EF_ACT) {
return "E" + getActionsStr() + "F(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AX_ACT) {
return "A" + getActionsStr() + "X(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AG_ACT) {
return "A" + getActionsStr() + "G(" + arg[0]->toStr() + ")";
}
else if (oper == RSCTL_AU_ACT) {
return "A" + getActionsStr() + "U(" + arg[0]->toStr() + "," + arg[1]->toStr()
+ ")";
}
else if (oper == RSCTL_AF_ACT) {
return "A" + getActionsStr() + "F(" + arg[0]->toStr() + ")";
}
else else {
{ return "??";
return "??"; assert(0);
assert(0); }
}
} }
bool FormRSCTL::hasOper(Oper op) const bool FormRSCTL::hasOper(Oper op) const
{ {
if (oper == op) if (oper == op) {
return true; return true;
else }
{ else {
bool result = false; bool result = false;
if (arg[0] != nullptr) result = arg[0]->hasOper(op);
if (!result && arg[1] != nullptr) result = arg[1]->hasOper(op); if (arg[0] != nullptr) {
return result; result = arg[0]->hasOper(op);
} }
if (!result && arg[1] != nullptr) {
result = arg[1]->hasOper(op);
}
return result;
}
} }
void FormRSCTL::encodeEntities(const SymRS *srs) void FormRSCTL::encodeEntities(const SymRS *srs)
{ {
if (RSCTL_COND_1ARG(oper)) if (RSCTL_COND_1ARG(oper)) {
{ arg[0]->encodeEntities(srs);
arg[0]->encodeEntities(srs); }
} else if (RSCTL_COND_2ARG(oper)) {
else if (RSCTL_COND_2ARG(oper)) arg[0]->encodeEntities(srs);
{ arg[1]->encodeEntities(srs);
arg[0]->encodeEntities(srs); }
arg[1]->encodeEntities(srs); else if (oper == RSCTL_PV) {
} bdd = new BDD(srs->encEntity(name));
else if (oper == RSCTL_PV) }
{
bdd = new BDD(srs->encEntity(name));
}
} }
bool FormRSCTL::isERSCTL(void) const bool FormRSCTL::isERSCTL(void) const
{ {
if (oper == RSCTL_PV) if (oper == RSCTL_PV) {
{ return true;
return true; }
if (oper == RSCTL_NOT) {
if (arg[0]->getOper() == RSCTL_PV || arg[0]->getOper() == RSCTL_TF) {
return true;
} }
else {
if (oper == RSCTL_NOT) return false;
{
if (arg[0]->getOper() == RSCTL_PV || arg[0]->getOper() == RSCTL_TF)
return true;
else
return false;
} }
}
if (RSCTL_COND_IS_UNIVERSAL(oper)) if (RSCTL_COND_IS_UNIVERSAL(oper)) {
{
return false;
}
if (RSCTL_COND_1ARG(oper))
{
return arg[0]->isERSCTL();
}
if (RSCTL_COND_2ARG(oper))
{
return arg[0]->isERSCTL() && arg[1]->isERSCTL();
}
assert(0);
return false; return false;
}
if (RSCTL_COND_1ARG(oper)) {
return arg[0]->isERSCTL();
}
if (RSCTL_COND_2ARG(oper)) {
return arg[0]->isERSCTL() && arg[1]->isERSCTL();
}
assert(0);
return false;
} }
std::string FormRSCTL::getActionsStr(void) const std::string FormRSCTL::getActionsStr(void) const
{ {
if (actions != nullptr) if (actions != nullptr) {
{ std::string r = "[ ";
std::string r = "[ "; bool firstact = true;
bool firstact = true;
for (ActionsVec_f::iterator act = actions->begin(); act != actions->end(); ++act) for (ActionsVec_f::iterator act = actions->begin(); act != actions->end();
{ ++act) {
if (!firstact) r += ","; if (!firstact) {
else firstact = false; r += ",";
r += "{"; }
bool firstent = true; else {
for (Action_f::iterator ent = act->begin(); ent != act->end(); ++ent) firstact = false;
{ }
if (!firstent) r += ",";
else firstent = false; r += "{";
r += *ent; bool firstent = true;
}
r += "}"; for (Action_f::iterator ent = act->begin(); ent != act->end(); ++ent) {
} if (!firstent) {
r += " ]"; r += ",";
return r; }
} else {
else if (boolCtx != nullptr) firstent = false;
{ }
return "< " + boolCtx->toStr() + " >";
} r += *ent;
else }
{
FERROR("Context not specified. This should not happen."); r += "}";
} }
r += " ]";
return r;
}
else if (boolCtx != nullptr) {
return "< " + boolCtx->toStr() + " >";
}
else {
FERROR("Context not specified. This should not happen.");
}
} }
void FormRSCTL::encodeActions(const SymRS *srs) void FormRSCTL::encodeActions(const SymRS *srs)
{ {
if (RSCTL_COND_ACT(oper)) if (RSCTL_COND_ACT(oper)) {
{ if (actions_bdd != nullptr) {
if (actions_bdd != nullptr) forgetActionsBDD(); forgetActionsBDD();
actions_bdd = new BDD(srs->getBDDfalse());
assert(actions != nullptr || boolCtx != nullptr);
assert(!(actions != nullptr && boolCtx != nullptr));
if (actions != nullptr)
{
for (ActionsVec_f::iterator act = actions->begin(); act != actions->end(); ++act)
{
BDD single_action = srs->getBDDtrue();
for (Action_f::iterator ent = act->begin(); ent != act->end(); ++ent)
{
single_action *= srs->encActStrEntity(*ent);
}
single_action = srs->compContext(single_action);
*actions_bdd += single_action;
}
}
else if (boolCtx != nullptr)
{
*actions_bdd = boolCtx->getBDD(srs);
}
else
assert(0);
} }
if (RSCTL_COND_1ARG(oper)) actions_bdd = new BDD(srs->getBDDfalse());
{ assert(actions != nullptr || boolCtx != nullptr);
arg[0]->encodeActions(srs); assert(!(actions != nullptr && boolCtx != nullptr));
}
if (RSCTL_COND_2ARG(oper)) if (actions != nullptr) {
{ for (ActionsVec_f::iterator act = actions->begin(); act != actions->end();
arg[0]->encodeActions(srs); ++act) {
arg[1]->encodeActions(srs); BDD single_action = srs->getBDDtrue();
for (Action_f::iterator ent = act->begin(); ent != act->end(); ++ent) {
single_action *= srs->encActStrEntity(*ent);
}
single_action = srs->compContext(single_action);
*actions_bdd += single_action;
}
} }
else if (boolCtx != nullptr) {
*actions_bdd = boolCtx->getBDD(srs);
}
else {
assert(0);
}
}
if (RSCTL_COND_1ARG(oper)) {
arg[0]->encodeActions(srs);
}
if (RSCTL_COND_2ARG(oper)) {
arg[0]->encodeActions(srs);
arg[1]->encodeActions(srs);
}
} }

View File

@@ -19,7 +19,7 @@
#define RSCTL_PV 0 // propositional variable #define RSCTL_PV 0 // propositional variable
#define RSCTL_AND 1 #define RSCTL_AND 1
#define RSCTL_OR 2 #define RSCTL_OR 2
#define RSCTL_XOR 3 #define RSCTL_XOR 3
#define RSCTL_NOT 4 #define RSCTL_NOT 4
#define RSCTL_IMPL 5 #define RSCTL_IMPL 5
#define RSCTL_EG 11 // Existential... #define RSCTL_EG 11 // Existential...
@@ -41,12 +41,12 @@
#define RSCTL_TF 50 // true/false #define RSCTL_TF 50 // true/false
/* For Boolean contexts: */ /* For Boolean contexts: */
#define BCTX_PV 60 #define BCTX_PV 60
#define BCTX_AND 61 #define BCTX_AND 61
#define BCTX_OR 62 #define BCTX_OR 62
#define BCTX_XOR 63 #define BCTX_XOR 63
#define BCTX_NOT 64 #define BCTX_NOT 64
#define BCTX_TF 70 #define BCTX_TF 70
#define RSCTL_COND_1ARG(a) ((a) == RSCTL_NOT || (a) == RSCTL_EG || (a) == RSCTL_EF || (a) == RSCTL_EX || (a) == RSCTL_AG || (a) == RSCTL_AF || (a) == RSCTL_AX || (a) == RSCTL_EG_ACT || (a) == RSCTL_EF_ACT || (a) == RSCTL_EX_ACT || (a) == RSCTL_AG_ACT || (a) == RSCTL_AF_ACT || (a) == RSCTL_AX_ACT) #define RSCTL_COND_1ARG(a) ((a) == RSCTL_NOT || (a) == RSCTL_EG || (a) == RSCTL_EF || (a) == RSCTL_EX || (a) == RSCTL_AG || (a) == RSCTL_AF || (a) == RSCTL_AX || (a) == RSCTL_EG_ACT || (a) == RSCTL_EF_ACT || (a) == RSCTL_EX_ACT || (a) == RSCTL_AG_ACT || (a) == RSCTL_AF_ACT || (a) == RSCTL_AX_ACT)
@@ -71,75 +71,82 @@ typedef vector<Action_f> ActionsVec_f;
class BoolContexts class BoolContexts
{ {
Oper oper; Oper oper;
BoolContexts *arg[2]; BoolContexts *arg[2];
std::string name; std::string name;
bool tf; bool tf;
public: public:
BoolContexts(std::string varName) BoolContexts(std::string varName)
{ {
oper = BCTX_PV; oper = BCTX_PV;
name = varName; name = varName;
arg[0] = nullptr; arg[0] = nullptr;
arg[1] = nullptr; arg[1] = nullptr;
} }
/** /**
* @brief Constructor for true/false. * @brief Constructor for true/false.
* *
* @param val value of the logical constant * @param val value of the logical constant
*/ */
BoolContexts(bool val) { BoolContexts(bool val)
oper = BCTX_TF; {
tf = val; oper = BCTX_TF;
arg[0] = nullptr; tf = val;
arg[1] = nullptr; arg[0] = nullptr;
} arg[1] = nullptr;
}
/** /**
* @brief Constructor for one-argument formula. * @brief Constructor for one-argument formula.
*/ */
BoolContexts(Oper op, BoolContexts *form1) { BoolContexts(Oper op, BoolContexts *form1)
assert(op == BCTX_NOT); {
oper = op; assert(op == BCTX_NOT);
arg[0] = form1; oper = op;
arg[1] = nullptr; arg[0] = form1;
} arg[1] = nullptr;
}
/** /**
* @brief Constructor for two-argument formula. * @brief Constructor for two-argument formula.
*/ */
BoolContexts(Oper op, BoolContexts *form1, BoolContexts *form2) { BoolContexts(Oper op, BoolContexts *form1, BoolContexts *form2)
assert(BCTX_COND_2ARG(op)); {
oper = op; assert(BCTX_COND_2ARG(op));
arg[0] = form1; oper = op;
arg[1] = form2; arg[0] = form1;
} arg[1] = form2;
}
~BoolContexts() { ~BoolContexts()
delete arg[0]; {
delete arg[1]; delete arg[0];
} delete arg[1];
}
std::string toStr(void) const; std::string toStr(void) const;
BDD getBDD(const SymRS *srs) const; BDD getBDD(const SymRS *srs) const;
Oper getOper(void) const { Oper getOper(void) const
assert(BCTX_IS_VALID(oper)); {
return oper; assert(BCTX_IS_VALID(oper));
} return oper;
BoolContexts *getLeftSF(void) const { }
assert(arg[0] != nullptr); BoolContexts *getLeftSF(void) const
return arg[0]; {
} assert(arg[0] != nullptr);
BoolContexts *getRightSF(void) const { return arg[0];
assert(BCTX_COND_2ARG(oper)); }
assert(arg[1] != nullptr); BoolContexts *getRightSF(void) const
return arg[1]; {
} assert(BCTX_COND_2ARG(oper));
assert(arg[1] != nullptr);
return arg[1];
}
}; };
class FormRSCTL class FormRSCTL
@@ -151,23 +158,24 @@ class FormRSCTL
BDD *bdd; BDD *bdd;
ActionsVec_f *actions; ActionsVec_f *actions;
BDD *actions_bdd; BDD *actions_bdd;
BoolContexts *boolCtx; BoolContexts *boolCtx;
public: public:
/** /**
* @brief Constructor for propositional variable. * @brief Constructor for propositional variable.
* *
* @param varName variable name used mostly for printing the variable. * @param varName variable name used mostly for printing the variable.
* @param varBDD the BDD describing the set where the variable holds. * @param varBDD the BDD describing the set where the variable holds.
*/ */
FormRSCTL(std::string varName) { FormRSCTL(std::string varName)
oper = RSCTL_PV; {
name = varName; oper = RSCTL_PV;
arg[0] = nullptr; name = varName;
arg[1] = nullptr; arg[0] = nullptr;
bdd = nullptr; arg[1] = nullptr;
actions = nullptr; bdd = nullptr;
actions_bdd = nullptr; actions = nullptr;
boolCtx = nullptr; actions_bdd = nullptr;
boolCtx = nullptr;
} }
/** /**
@@ -175,156 +183,173 @@ public:
* *
* @param val value of the logical constant * @param val value of the logical constant
*/ */
FormRSCTL(bool val) { FormRSCTL(bool val)
oper = RSCTL_TF; {
tf = val; oper = RSCTL_TF;
arg[0] = nullptr; tf = val;
arg[1] = nullptr; arg[0] = nullptr;
bdd = nullptr; arg[1] = nullptr;
actions = nullptr; bdd = nullptr;
actions_bdd = nullptr; actions = nullptr;
boolCtx = nullptr; actions_bdd = nullptr;
boolCtx = nullptr;
} }
/** /**
* @brief Constructor for two-argument formula. * @brief Constructor for two-argument formula.
*/ */
FormRSCTL(Oper op, FormRSCTL *form1, FormRSCTL *form2) { FormRSCTL(Oper op, FormRSCTL *form1, FormRSCTL *form2)
assert(RSCTL_COND_2ARG(op)); {
assert(!RSCTL_COND_ACT(op)); assert(RSCTL_COND_2ARG(op));
oper = op; assert(!RSCTL_COND_ACT(op));
arg[0] = form1; oper = op;
arg[1] = form2; arg[0] = form1;
bdd = nullptr; arg[1] = form2;
actions = nullptr; bdd = nullptr;
actions_bdd = nullptr; actions = nullptr;
boolCtx = nullptr; actions_bdd = nullptr;
boolCtx = nullptr;
} }
/** /**
* @brief Constructor for two-argument formula with action restrictions. * @brief Constructor for two-argument formula with action restrictions.
*/ */
FormRSCTL(Oper op, ActionsVec_f *acts, FormRSCTL *form1, FormRSCTL *form2) { FormRSCTL(Oper op, ActionsVec_f *acts, FormRSCTL *form1, FormRSCTL *form2)
assert(acts != nullptr); {
assert(RSCTL_COND_2ARG(op)); assert(acts != nullptr);
assert(RSCTL_COND_ACT(op)); assert(RSCTL_COND_2ARG(op));
oper = op; assert(RSCTL_COND_ACT(op));
arg[0] = form1; oper = op;
arg[1] = form2; arg[0] = form1;
bdd = nullptr; arg[1] = form2;
actions = acts; bdd = nullptr;
actions_bdd = nullptr; actions = acts;
boolCtx = nullptr; actions_bdd = nullptr;
boolCtx = nullptr;
} }
/** /**
* @brief Constructor for two-argument formula with Boolean context restrictions. * @brief Constructor for two-argument formula with Boolean context restrictions.
*/ */
FormRSCTL(Oper op, BoolContexts *bctx, FormRSCTL *form1, FormRSCTL *form2) { FormRSCTL(Oper op, BoolContexts *bctx, FormRSCTL *form1, FormRSCTL *form2)
assert(bctx != nullptr); {
assert(RSCTL_COND_2ARG(op)); assert(bctx != nullptr);
assert(RSCTL_COND_ACT(op)); assert(RSCTL_COND_2ARG(op));
oper = op; assert(RSCTL_COND_ACT(op));
arg[0] = form1; oper = op;
arg[1] = form2; arg[0] = form1;
bdd = nullptr; arg[1] = form2;
actions = nullptr; bdd = nullptr;
actions_bdd = nullptr; actions = nullptr;
boolCtx = bctx; actions_bdd = nullptr;
} boolCtx = bctx;
}
/** /**
* @brief Constructor for one-argument formula. * @brief Constructor for one-argument formula.
*/ */
FormRSCTL(Oper op, FormRSCTL *form1) { FormRSCTL(Oper op, FormRSCTL *form1)
assert(RSCTL_COND_1ARG(op)); {
assert(!RSCTL_COND_ACT(op)); assert(RSCTL_COND_1ARG(op));
oper = op; assert(!RSCTL_COND_ACT(op));
arg[0] = form1; oper = op;
arg[1] = nullptr; arg[0] = form1;
bdd = nullptr; arg[1] = nullptr;
actions = nullptr; bdd = nullptr;
actions_bdd = nullptr; actions = nullptr;
boolCtx = nullptr; actions_bdd = nullptr;
boolCtx = nullptr;
} }
/** /**
* @brief Constructor for one-argument formula with action restrictions. * @brief Constructor for one-argument formula with action restrictions.
*/ */
FormRSCTL(Oper op, ActionsVec_f *acts, FormRSCTL *form1) { FormRSCTL(Oper op, ActionsVec_f *acts, FormRSCTL *form1)
assert(acts != nullptr); {
assert(RSCTL_COND_1ARG(op)); assert(acts != nullptr);
assert(RSCTL_COND_ACT(op)); assert(RSCTL_COND_1ARG(op));
oper = op; assert(RSCTL_COND_ACT(op));
arg[0] = form1; oper = op;
arg[1] = nullptr; arg[0] = form1;
bdd = nullptr; arg[1] = nullptr;
actions = acts; bdd = nullptr;
actions_bdd = nullptr; actions = acts;
boolCtx = nullptr; actions_bdd = nullptr;
boolCtx = nullptr;
} }
/** /**
* @brief Constructor for one-argument formula with Boolean context restrictions. * @brief Constructor for one-argument formula with Boolean context restrictions.
*/ */
FormRSCTL(Oper op, BoolContexts *bctx, FormRSCTL *form1) { FormRSCTL(Oper op, BoolContexts *bctx, FormRSCTL *form1)
assert(bctx != nullptr); {
assert(RSCTL_COND_1ARG(op)); assert(bctx != nullptr);
assert(RSCTL_COND_ACT(op)); assert(RSCTL_COND_1ARG(op));
oper = op; assert(RSCTL_COND_ACT(op));
arg[0] = form1; oper = op;
arg[1] = nullptr; arg[0] = form1;
bdd = nullptr; arg[1] = nullptr;
actions = nullptr; bdd = nullptr;
actions_bdd = nullptr; actions = nullptr;
boolCtx = bctx; actions_bdd = nullptr;
} boolCtx = bctx;
}
/** /**
* @brief Destructor. * @brief Destructor.
*/ */
~FormRSCTL() { ~FormRSCTL()
delete arg[0]; {
delete arg[1]; delete arg[0];
delete bdd; delete arg[1];
delete actions; delete bdd;
delete actions_bdd; delete actions;
delete boolCtx; delete actions_bdd;
delete boolCtx;
} }
std::string toStr(void) const; std::string toStr(void) const;
bool hasOper(Oper op) const; bool hasOper(Oper op) const;
const BDD *getBDD(void) const { const BDD *getBDD(void) const
assert(oper == RSCTL_PV); {
assert(bdd != nullptr); assert(oper == RSCTL_PV);
return bdd; assert(bdd != nullptr);
return bdd;
} }
const BDD *getActionsBDD(void) const { const BDD *getActionsBDD(void) const
assert(RSCTL_COND_ACT(oper)); {
assert(actions_bdd != nullptr); assert(RSCTL_COND_ACT(oper));
return actions_bdd; assert(actions_bdd != nullptr);
return actions_bdd;
} }
Oper getOper(void) const { Oper getOper(void) const
assert(RSCTL_IS_VALID(oper)); {
return oper; assert(RSCTL_IS_VALID(oper));
return oper;
} }
FormRSCTL *getLeftSF(void) const { FormRSCTL *getLeftSF(void) const
assert(arg[0] != nullptr); {
return arg[0]; assert(arg[0] != nullptr);
return arg[0];
} }
FormRSCTL *getRightSF(void) const { FormRSCTL *getRightSF(void) const
assert(RSCTL_COND_2ARG(oper)); {
assert(arg[1] != nullptr); assert(RSCTL_COND_2ARG(oper));
return arg[1]; assert(arg[1] != nullptr);
return arg[1];
} }
std::string getActionsStr(void) const; std::string getActionsStr(void) const;
bool getTF(void) const { bool getTF(void) const
assert(oper == RSCTL_TF); {
return tf; assert(oper == RSCTL_TF);
return tf;
} }
void encodeEntities(const SymRS *srs); void encodeEntities(const SymRS *srs);
void encodeActions(const SymRS *srs); void encodeActions(const SymRS *srs);
void forgetActionsBDD(void) { void forgetActionsBDD(void)
if (actions_bdd != nullptr) delete actions_bdd; {
if (actions_bdd != nullptr) {
delete actions_bdd;
}
} }
bool isERSCTL(void) const; bool isERSCTL(void) const;
}; };

View File

@@ -7,8 +7,8 @@
/* Fatal error */ /* Fatal error */
#define FERROR(s) \ #define FERROR(s) \
{ \ { \
std::cerr << "EE: " << __FILE__ << " (function " << __func__ << "), line " << __LINE__ << ": " << s << std::endl; \ std::cerr << "EE: " << __FILE__ << " (function " << __func__ << "), line " << __LINE__ << ": " << s << std::endl; \
exit(1); \ exit(1); \
} }
#define WARNING(s) \ #define WARNING(s) \
{ \ { \
@@ -18,25 +18,25 @@
#define VERB(s) \ #define VERB(s) \
assert(opts != nullptr); \ assert(opts != nullptr); \
if (opts->verbose > 0) { \ if (opts->verbose > 0) { \
std::cerr << "ii VERBOSE(1): " << __FILE__ << " (" << __func__ << ":" << __LINE__ << "): " << s << std::endl; \ std::cerr << "ii VERBOSE(1): " << __FILE__ << " (" << __func__ << ":" << __LINE__ << "): " << s << std::endl; \
} }
#define VERB_L2(s) \ #define VERB_L2(s) \
assert(opts != nullptr); \ assert(opts != nullptr); \
if (opts->verbose > 1) { \ if (opts->verbose > 1) { \
std::cerr << "ii VERBOSE(2): " << __FILE__ << " (" << __func__ << ":" << __LINE__ << "): " << s << std::endl; \ std::cerr << "ii VERBOSE(2): " << __FILE__ << " (" << __func__ << ":" << __LINE__ << "): " << s << std::endl; \
} }
#define VERB_L3(s) \ #define VERB_L3(s) \
assert(opts != nullptr); \ assert(opts != nullptr); \
if (opts->verbose > 2) { \ if (opts->verbose > 2) { \
std::cerr << "ii VERBOSE(3): " << __FILE__ << " (" << __func__ << ":" << __LINE__ << "): " << s << std::endl; \ std::cerr << "ii VERBOSE(3): " << __FILE__ << " (" << __func__ << ":" << __LINE__ << "): " << s << std::endl; \
} }
#define VERB_LN(n,s) \ #define VERB_LN(n,s) \
assert(opts != nullptr); \ assert(opts != nullptr); \
if (opts->verbose >= (n)) { \ if (opts->verbose >= (n)) { \
std::cerr << "ii VERBOSE(" << (n) << "): " << __FILE__ << " (" << __func__ << ":" << __LINE__ << "): " << s << std::endl; \ std::cerr << "ii VERBOSE(" << (n) << "): " << __FILE__ << " (" << __func__ << ":" << __LINE__ << "): " << s << std::endl; \
} }
#endif #endif

425
main.cc
View File

@@ -10,236 +10,249 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
rsin_driver driver; rsin_driver driver;
Options *opts = new Options; Options *opts = new Options;
driver.setOptions(opts); driver.setOptions(opts);
bool show_reactions = false; bool show_reactions = false;
bool rstl_model_checking = false; bool rstl_model_checking = false;
bool reach_states = false; bool reach_states = false;
bool reach_states_succ = false; bool reach_states_succ = false;
bool bmc = true; bool bmc = true;
bool benchmarking = false; bool benchmarking = false;
bool usage_error = false; bool usage_error = false;
bool print_parsed_sys = false; bool print_parsed_sys = false;
static struct option long_options[] = static struct option long_options[] = {
{ {"trace-parsing", no_argument, 0, 0 },
{"trace-parsing", no_argument, 0, 0 }, {"trace-scanning", no_argument, 0, 0 },
{"trace-scanning", no_argument, 0, 0 }, {0, 0, 0, 0 }
{0, 0, 0, 0 } };
};
int c; int c;
int option_index = 0; int option_index = 0;
while ((c = getopt_long(argc, argv, "cbBmpPrsStTvxzh", long_options, &option_index)) != -1) while ((c = getopt_long(argc, argv, "cbBmpPrsStTvxzh", long_options,
{ &option_index)) != -1) {
switch (c) { switch (c) {
case 0: case 0:
printf("option %s", long_options[option_index].name); printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
if (strcmp(long_options[option_index].name, "trace-parsing")) if (optarg) {
driver.trace_parsing = true; printf(" with arg %s", optarg);
else if (strcmp(long_options[option_index].name, "trace-scanning"))
driver.trace_scanning = true;
break;
//case 'b':
// printf("-b with %s\n", optarg);
// break;
case 'b':
bmc = false;
break;
case 'p':
opts->show_progress = true;
break;
case 'P':
print_parsed_sys = true;
break;
case 'r':
show_reactions = true;
break;
case 'c':
rstl_model_checking = true;
break;
case 'm':
opts->measure = true;
break;
case 'B':
benchmarking = true;
opts->measure = true;
break;
case 's':
reach_states = true;
break;
case 't':
reach_states_succ = true;
break;
case 'v':
opts->verbose++;
break;
case 'x':
opts->part_tr_rel = true;
break;
case 'z':
opts->reorder_reach = true;
opts->reorder_trans = true;
break;
case 'h':
usage_error = true;
break;
default:
usage_error = true;
break;
} }
}
std::string inputfile; printf("\n");
if (optind < argc)
{ if (strcmp(long_options[option_index].name, "trace-parsing")) {
inputfile = argv[optind]; driver.trace_parsing = true;
} }
else else if (strcmp(long_options[option_index].name, "trace-scanning")) {
{ driver.trace_scanning = true;
cout << "Missing input file" << endl; }
break;
//case 'b':
// printf("-b with %s\n", optarg);
// break;
case 'b':
bmc = false;
break;
case 'p':
opts->show_progress = true;
break;
case 'P':
print_parsed_sys = true;
break;
case 'r':
show_reactions = true;
break;
case 'c':
rstl_model_checking = true;
break;
case 'm':
opts->measure = true;
break;
case 'B':
benchmarking = true;
opts->measure = true;
break;
case 's':
reach_states = true;
break;
case 't':
reach_states_succ = true;
break;
case 'v':
opts->verbose++;
break;
case 'x':
opts->part_tr_rel = true;
break;
case 'z':
opts->reorder_reach = true;
opts->reorder_trans = true;
break;
case 'h':
usage_error = true; usage_error = true;
break;
default:
usage_error = true;
break;
}
}
std::string inputfile;
if (optind < argc) {
inputfile = argv[optind];
}
else {
cout << "Missing input file" << endl;
usage_error = true;
}
if (usage_error) {
print_help(std::string(argv[0]));
return 100;
}
if (!(reach_states || reach_states_succ || rstl_model_checking
|| show_reactions || print_parsed_sys)) {
FERROR("No task specified: -c, -P, -r, or -s needs to be used");
}
if (opts->verbose > 0) {
cout << "Verbose level: " << opts->verbose << endl;
}
VERB("Parsing " << inputfile);
if (driver.parse(inputfile)) {
FERROR("Parse error");
}
//
// Here we retrieve the reaction system from the parser
//
// We decide which RS will be used at the parser level.
// This decision depends on whether we use concentrations,
// context automaton, etc.
//
auto rs = *driver.getReactionSystem();
rs.setOptions(opts); // these need to be passed to the driver
if (show_reactions) {
rs.showReactions();
}
if (print_parsed_sys) {
rs.printSystem();
}
if (reach_states || reach_states_succ || rstl_model_checking) {
SymRS srs(&rs, opts);
ModelChecker mc(&srs, opts);
if (reach_states) {
mc.printReach();
} }
if (usage_error) if (reach_states_succ) {
{ mc.printReachWithSucc();
print_help(std::string(argv[0]));
return 100;
} }
if (!(reach_states || reach_states_succ || rstl_model_checking || show_reactions || print_parsed_sys)) if (rstl_model_checking) {
{ if (bmc) {
FERROR("No task specified: -c, -P, -r, or -s needs to be used"); cout << "Using BDD-based Bounded Model Checking" << endl;
mc.checkRSCTL(driver.getFormRSCTL());
}
else {
mc.checkRSCTLfull(driver.getFormRSCTL());
}
} }
}
if (opts->measure) {
cout << endl << std::setprecision(4)
<< "Encoding time: " << opts->enc_time << " sec" << endl
<< "Verification time: " << opts->ver_time << " sec" << endl
<< "Encoding memory: " << opts->enc_mem << " MB" << endl
<< "Memory (total): " << opts->ver_mem << " MB" << endl
<< "TOTAL time: " << opts->enc_time + opts->ver_time << " sec" << endl;
if (benchmarking) {
cout << std::setprecision(4)
<< "STAT; " << opts->enc_time
<< " ; " << opts->ver_time
<< " ; " << opts->enc_mem
<< " ; " << opts->ver_mem
<< " ; " << opts->enc_time + opts->ver_time << endl;
if (opts->verbose > 0)
{
cout << "Verbose level: " << opts->verbose << endl;
} }
}
VERB("Parsing " << inputfile); delete opts;
if (driver.parse(inputfile)) return 0;
{
FERROR("Parse error");
}
//
// Here we retrieve the reaction system from the parser
//
// We decide which RS will be used at the parser level.
// This decision depends on whether we use concentrations,
// context automaton, etc.
//
auto rs = *driver.getReactionSystem();
rs.setOptions(opts); // these need to be passed to the driver
if (show_reactions)
rs.showReactions();
if (print_parsed_sys)
rs.printSystem();
if (reach_states || reach_states_succ || rstl_model_checking)
{
SymRS srs(&rs, opts);
ModelChecker mc(&srs, opts);
if (reach_states)
{
mc.printReach();
}
if (reach_states_succ)
{
mc.printReachWithSucc();
}
if (rstl_model_checking)
{
if (bmc)
{
cout << "Using BDD-based Bounded Model Checking" << endl;
mc.checkRSCTL(driver.getFormRSCTL());
}
else
{
mc.checkRSCTLfull(driver.getFormRSCTL());
}
}
}
if (opts->measure)
{
cout << endl << std::setprecision(4)
<< "Encoding time: " << opts->enc_time << " sec" << endl
<< "Verification time: " << opts->ver_time << " sec" << endl
<< "Encoding memory: " << opts->enc_mem << " MB" << endl
<< "Memory (total): " << opts->ver_mem << " MB" << endl
<< "TOTAL time: " << opts->enc_time + opts->ver_time << " sec" << endl;
if (benchmarking)
{
cout << std::setprecision(4)
<< "STAT; " << opts->enc_time
<< " ; " << opts->ver_time
<< " ; " << opts->enc_mem
<< " ; " << opts->ver_mem
<< " ; " << opts->enc_time+opts->ver_time << endl;
}
}
delete opts;
return 0;
} }
void print_help(std::string path_str) void print_help(std::string path_str)
{ {
cout << endl cout << endl
<< " ------------------------------------" << endl << " ------------------------------------" << endl
<< " -- Reaction Systems Model Checker --" << endl << " -- Reaction Systems Model Checker --" << endl
<< " ------------------------------------" << endl << " ------------------------------------" << endl
<< endl << endl
<< " Version: " << VERSION << endl << " Version: " << VERSION << endl
<< " Contact: " << AUTHOR << endl << " Contact: " << AUTHOR << endl
<< endl << endl
#ifndef PUBLIC_RELEASE #ifndef PUBLIC_RELEASE
<< " ###################################" << endl << " ###################################" << endl
<< " THIS IS A PRIVATE VERSION OF RSMC " << endl << " THIS IS A PRIVATE VERSION OF RSMC " << endl
<< " PLEASE, DO NOT DISTRIBUTE " << endl << " PLEASE, DO NOT DISTRIBUTE " << endl
<< " ###################################" << endl << " ###################################" << endl
<< endl << endl
#endif #endif
<< " Usage: " << path_str << " [options] <inputfile>" << endl << endl << " Usage: " << path_str << " [options] <inputfile>" << endl << endl
<< " TASKS:" << endl << " TASKS:" << endl
<< " -c -- perform RSCTL model checking" << endl << " -c -- perform RSCTL model checking" << endl
//<< " -f K -- generate SMT input for the depth K" << endl //<< " -f K -- generate SMT input for the depth K" << endl
<< " -P -- print parsed system" << endl << " -P -- print parsed system" << endl
<< " -r -- print reactions" << endl << " -r -- print reactions" << endl
<< " -s -- print the set of all the reachable states" << endl << " -s -- print the set of all the reachable states" << endl
<< " -t -- print the set of all the reachable states with their successors" << endl << " -t -- print the set of all the reachable states with their successors"
<< endl << " OTHER:" << endl << endl
<< " -b -- disable bounded model checking (BMC) heuristic" << endl << endl << " OTHER:" << endl
<< " -x -- use partitioned transition relation (may use less memory)" << endl << " -b -- disable bounded model checking (BMC) heuristic" << endl
<< " -z -- use reordering of the BDD variables" << endl << " -x -- use partitioned transition relation (may use less memory)" <<
<< " -v -- verbose (can be used more than once to increase verbosity)" << endl endl
<< " -p -- show progress (where possible)" << endl << " -z -- use reordering of the BDD variables" << endl
<< endl << " -v -- verbose (can be used more than once to increase verbosity)" <<
<< " Benchmarking options:" << endl endl
<< " -m -- measure and display time and memory usage" << endl << " -p -- show progress (where possible)" << endl
<< " -B -- display an easy to parse summary (enables -m)" << endl << endl
<< endl; << " Benchmarking options:" << endl
<< " -m -- measure and display time and memory usage" << endl
<< " -B -- display an easy to parse summary (enables -m)" << endl
<< endl;
} }
/** EOF **/ /** EOF **/

851
mc.cc
View File

@@ -1,572 +1,567 @@
#include "mc.hh" #include "mc.hh"
ModelChecker::ModelChecker(SymRS *srs, Options *opts) ModelChecker::ModelChecker(SymRS *srs, Options *opts)
: using_ctx_aut(false) : using_ctx_aut(false)
{ {
this->srs = srs; this->srs = srs;
this->opts = opts; this->opts = opts;
cuddMgr = srs->getCuddMgr(); cuddMgr = srs->getCuddMgr();
initStates = srs->getEncInitStates(); initStates = srs->getEncInitStates();
totalStateVars = srs->getTotalStateVars(); totalStateVars = srs->getTotalStateVars();
pv = srs->getEncPV(); pv = srs->getEncPV();
pv_succ = srs->getEncPVsucc(); pv_succ = srs->getEncPVsucc();
pv_E = srs->getEncPV_E(); pv_E = srs->getEncPV_E();
pv_succ_E = srs->getEncPVsucc_E(); pv_succ_E = srs->getEncPVsucc_E();
pv_act_E = srs->getEncPVact_E(); pv_act_E = srs->getEncPVact_E();
// //
// Transition relations // Transition relations
// //
// trp -- partitioned TR // trp -- partitioned TR
// trm -- monolithic TR // trm -- monolithic TR
// //
// If we use trp, then trm is nullptr (same for trm) // If we use trp, then trm is nullptr (same for trm)
// //
trp = srs->getEncPartTrans(); trp = srs->getEncPartTrans();
if (trp == nullptr)
trp_size = 0;
else
trp_size = trp->size();
trm = srs->getEncMonoTrans();
if (srs->usingContextAutomaton()) if (trp == nullptr) {
{ trp_size = 0;
using_ctx_aut = true; }
pv_ca = srs->getEncCtxAutPV(); else {
pv_ca_succ = srs->getEncCtxAutPVsucc(); trp_size = trp->size();
pv_ca_E = srs->getEncCtxAutPV_E(); }
pv_ca_succ_E = srs->getEncCtxAutPVsucc_E();
}
else
{
using_ctx_aut = false;
pv_ca = nullptr;
pv_ca_succ = nullptr;
pv_ca_E = nullptr;
pv_ca_succ_E = nullptr;
}
// Initialise the set of reachable states trm = srs->getEncMonoTrans();
reach = nullptr;
if (srs->usingContextAutomaton()) {
using_ctx_aut = true;
pv_ca = srs->getEncCtxAutPV();
pv_ca_succ = srs->getEncCtxAutPVsucc();
pv_ca_E = srs->getEncCtxAutPV_E();
pv_ca_succ_E = srs->getEncCtxAutPVsucc_E();
}
else {
using_ctx_aut = false;
pv_ca = nullptr;
pv_ca_succ = nullptr;
pv_ca_E = nullptr;
pv_ca_succ_E = nullptr;
}
// Initialise the set of reachable states
reach = nullptr;
} }
inline BDD ModelChecker::getSucc(const BDD &states) inline BDD ModelChecker::getSucc(const BDD &states)
{ {
BDD q = BDD_TRUE; BDD q = BDD_TRUE;
VERB_L2("Computing successors"); VERB_L2("Computing successors");
if (opts->part_tr_rel)
{
for (unsigned int i = 0; i < trp_size; ++i)
{
q *= states * (*trp)[i];
}
}
else
{
q *= states * *trm;
}
q = (q.ExistAbstract(*pv_E)).SwapVariables(*pv_succ, *pv);
q = q.ExistAbstract(*pv_act_E);
return q; if (opts->part_tr_rel) {
for (unsigned int i = 0; i < trp_size; ++i) {
q *= states * (*trp)[i];
}
}
else {
q *= states * *trm;
}
q = (q.ExistAbstract(*pv_E)).SwapVariables(*pv_succ, *pv);
q = q.ExistAbstract(*pv_act_E);
return q;
} }
inline BDD ModelChecker::getPreE(const BDD &states) inline BDD ModelChecker::getPreE(const BDD &states)
{ {
BDD q = BDD_TRUE; BDD q = BDD_TRUE;
VERB_L2("Computing preE"); VERB_L2("Computing preE");
BDD x = states.SwapVariables(*pv, *pv_succ); BDD x = states.SwapVariables(*pv, *pv_succ);
if (opts->part_tr_rel)
{ if (opts->part_tr_rel) {
for (unsigned int i = 0; i < trp_size; ++i) for (unsigned int i = 0; i < trp_size; ++i) {
q *= x * (*trp)[i]; q *= x * (*trp)[i];
} }
else }
{ else {
q *= x * *trm; q *= x * *trm;
} }
q = q.ExistAbstract(*pv_succ_E);
q = q.ExistAbstract(*pv_act_E); q = q.ExistAbstract(*pv_succ_E);
return q; q = q.ExistAbstract(*pv_act_E);
return q;
} }
inline BDD ModelChecker::getPreEctx(const BDD &states, const BDD *contexts) inline BDD ModelChecker::getPreEctx(const BDD &states, const BDD *contexts)
{ {
BDD q = BDD_TRUE; BDD q = BDD_TRUE;
VERB_L2("Computing (context-restricted) preE"); VERB_L2("Computing (context-restricted) preE");
BDD x = states.SwapVariables(*pv, *pv_succ); BDD x = states.SwapVariables(*pv, *pv_succ);
if (opts->part_tr_rel)
{ if (opts->part_tr_rel) {
for (unsigned int i = 0; i < trp_size; ++i) for (unsigned int i = 0; i < trp_size; ++i) {
q *= x * (*trp)[i] * *contexts; q *= x * (*trp)[i] * *contexts;
} }
else }
{ else {
q *= x * *trm * *contexts; q *= x * *trm * *contexts;
} }
q = q.ExistAbstract(*pv_succ_E);
q = q.ExistAbstract(*pv_act_E); q = q.ExistAbstract(*pv_succ_E);
return q; q = q.ExistAbstract(*pv_act_E);
return q;
} }
void ModelChecker::dropCtxAutStatePart(BDD &states) void ModelChecker::dropCtxAutStatePart(BDD &states)
{ {
states = states.ExistAbstract(*pv_ca_E); states = states.ExistAbstract(*pv_ca_E);
} }
void ModelChecker::printReach(void) void ModelChecker::printReach(void)
{ {
VERB_LN(2, "Printing/generating reachable states"); VERB_LN(2, "Printing/generating reachable states");
if (opts->measure) if (opts->measure) {
opts->ver_time = cpuTime(); opts->ver_time = cpuTime();
}
assert(initStates != nullptr); assert(initStates != nullptr);
BDD *reach = new BDD(*initStates); BDD *reach = new BDD(*initStates);
BDD reach_p = BDD_FALSE; BDD reach_p = BDD_FALSE;
unsigned int k = 0; unsigned int k = 0;
while (*reach != reach_p) while (*reach != reach_p) {
{ if (opts->show_progress) {
if (opts->show_progress) cout << "\rIteration " << ++k << flush;
{
cout << "\rIteration " << ++k << flush;
}
reach_p = *reach;
*reach += getSucc(*reach);
} }
dropCtxAutStatePart(*reach); reach_p = *reach;
*reach += getSucc(*reach);
}
srs->printDecodedRctSysStates(*reach); dropCtxAutStatePart(*reach);
cleanup(); srs->printDecodedRctSysStates(*reach);
if (opts->measure) cleanup();
{
opts->ver_time = cpuTime() - opts->ver_time; if (opts->measure) {
opts->ver_mem = memUsed(); opts->ver_time = cpuTime() - opts->ver_time;
} opts->ver_mem = memUsed();
}
} }
void ModelChecker::printReachWithSucc(void) void ModelChecker::printReachWithSucc(void)
{ {
VERB_LN(2, "Printing/generating reachable states (with successors)"); VERB_LN(2, "Printing/generating reachable states (with successors)");
BDD *reach = new BDD(*initStates); BDD *reach = new BDD(*initStates);
BDD reach_p = cuddMgr->bddZero(); BDD reach_p = cuddMgr->bddZero();
while (*reach != reach_p) while (*reach != reach_p) {
{ reach_p = *reach;
reach_p = *reach; BDD newStates = getSucc(*reach) - *reach;
BDD newStates = getSucc(*reach) - *reach; *reach += newStates;
*reach += newStates;
} }
BDD unproc = *reach; BDD unproc = *reach;
while (!unproc.IsZero())
{
BDD t;
t = unproc.PickOneMinterm(*pv);
cout << "Successors of " << srs->decodedRctSysStateToStr(t) << ":" << endl;
srs->printDecodedRctSysStates(getSucc(t));
unproc -= t;
}
cleanup(); while (!unproc.IsZero()) {
BDD t;
t = unproc.PickOneMinterm(*pv);
cout << "Successors of " << srs->decodedRctSysStateToStr(t) << ":" << endl;
srs->printDecodedRctSysStates(getSucc(t));
unproc -= t;
}
cleanup();
} }
bool ModelChecker::checkReach(const Entities testState) bool ModelChecker::checkReach(const Entities testState)
{ {
if (opts->measure) if (opts->measure) {
opts->ver_time = cpuTime(); opts->ver_time = cpuTime();
}
BDD st = srs->getEncState(testState); BDD st = srs->getEncState(testState);
BDD reach = *initStates; BDD reach = *initStates;
BDD reach_p = cuddMgr->bddZero(); BDD reach_p = cuddMgr->bddZero();
while (reach != reach_p) while (reach != reach_p) {
{ if (reach * st != cuddMgr->bddZero()) {
if (reach * st != cuddMgr->bddZero()) cleanup();
{ return true;
cleanup();
return true;
}
reach_p = reach;
reach += getSucc(reach);
} }
cleanup(); reach_p = reach;
reach += getSucc(reach);
}
if (opts->measure) cleanup();
{
opts->ver_time = cpuTime() - opts->ver_time;
opts->ver_mem = memUsed();
}
return false; if (opts->measure) {
opts->ver_time = cpuTime() - opts->ver_time;
opts->ver_mem = memUsed();
}
return false;
} }
BDD ModelChecker::getStatesRSCTL(const FormRSCTL *form) BDD ModelChecker::getStatesRSCTL(const FormRSCTL *form)
{ {
assert(reach != nullptr); assert(reach != nullptr);
Oper oper = form->getOper(); Oper oper = form->getOper();
if (oper == RSCTL_PV)
{
return *form->getBDD() * *reach;
}
else if (oper == RSCTL_TF)
{
if (form->getTF() == true)
return *reach;
else
return cuddMgr->bddZero();
}
else if (oper == RSCTL_AND)
{
return getStatesRSCTL(form->getLeftSF()) * getStatesRSCTL(form->getRightSF());
}
else if (oper == RSCTL_OR)
{
return getStatesRSCTL(form->getLeftSF()) + getStatesRSCTL(form->getRightSF());
}
else if (oper == RSCTL_XOR)
{
return getStatesRSCTL(form->getLeftSF()) ^ getStatesRSCTL(form->getRightSF());
}
else if (oper == RSCTL_IMPL)
{
return (!getStatesRSCTL(form->getLeftSF()) * *reach) + getStatesRSCTL(form->getRightSF());
}
else if (oper == RSCTL_NOT)
{
return !getStatesRSCTL(form->getLeftSF()) * *reach;
}
else if (oper == RSCTL_EX)
{
return getPreE(getStatesRSCTL(form->getLeftSF())) * *reach;
}
else if (oper == RSCTL_EG)
{
return statesEG(getStatesRSCTL(form->getLeftSF()));
}
else if (oper == RSCTL_EU)
{
return statesEU(
getStatesRSCTL(form->getLeftSF()),
getStatesRSCTL(form->getRightSF())
);
}
else if (oper == RSCTL_EF)
{
return statesEF(getStatesRSCTL(form->getLeftSF()));
}
else if (oper == RSCTL_AX)
{
return !getPreE(!getStatesRSCTL(form->getLeftSF()) * *reach) * *reach;
}
else if (oper == RSCTL_AG)
{
return !statesEF(
!getStatesRSCTL(form->getLeftSF()) * *reach) * *reach;
}
else if (oper == RSCTL_AU)
{
BDD ng = !getStatesRSCTL(form->getRightSF()) * *reach;
BDD nf = !getStatesRSCTL(form->getLeftSF()) * *reach;
BDD x = !statesEU(ng, ng * nf) * *reach; if (oper == RSCTL_PV) {
if (!x.IsZero()) return *form->getBDD() * *reach;
x = x * !statesEG(ng) * *reach; }
else if (oper == RSCTL_TF) {
if (form->getTF() == true) {
return *reach;
}
else {
return cuddMgr->bddZero();
}
}
else if (oper == RSCTL_AND) {
return getStatesRSCTL(form->getLeftSF()) * getStatesRSCTL(form->getRightSF());
}
else if (oper == RSCTL_OR) {
return getStatesRSCTL(form->getLeftSF()) + getStatesRSCTL(form->getRightSF());
}
else if (oper == RSCTL_XOR) {
return getStatesRSCTL(form->getLeftSF()) ^ getStatesRSCTL(form->getRightSF());
}
else if (oper == RSCTL_IMPL) {
return (!getStatesRSCTL(form->getLeftSF()) * *reach) + getStatesRSCTL(
form->getRightSF());
}
else if (oper == RSCTL_NOT) {
return !getStatesRSCTL(form->getLeftSF()) * *reach;
}
else if (oper == RSCTL_EX) {
return getPreE(getStatesRSCTL(form->getLeftSF())) * *reach;
}
else if (oper == RSCTL_EG) {
return statesEG(getStatesRSCTL(form->getLeftSF()));
}
else if (oper == RSCTL_EU) {
return statesEU(
getStatesRSCTL(form->getLeftSF()),
getStatesRSCTL(form->getRightSF())
);
}
else if (oper == RSCTL_EF) {
return statesEF(getStatesRSCTL(form->getLeftSF()));
}
else if (oper == RSCTL_AX) {
return !getPreE(!getStatesRSCTL(form->getLeftSF()) * *reach) * *reach;
}
else if (oper == RSCTL_AG) {
return !statesEF(
!getStatesRSCTL(form->getLeftSF()) * *reach) * *reach;
}
else if (oper == RSCTL_AU) {
BDD ng = !getStatesRSCTL(form->getRightSF()) * *reach;
BDD nf = !getStatesRSCTL(form->getLeftSF()) * *reach;
return x; BDD x = !statesEU(ng, ng * nf) * *reach;
}
else if (oper == RSCTL_AF)
{
return !statesEG(
!getStatesRSCTL(form->getLeftSF()) * *reach) * *reach;
}
/***** CONTEXT RESTRICTIONS: ******/
else if (oper == RSCTL_EX_ACT)
{
return getPreEctx(getStatesRSCTL(form->getLeftSF()), form->getActionsBDD()) * *reach;
}
else if (oper == RSCTL_EG_ACT)
{
return statesEGctx(form->getActionsBDD(), getStatesRSCTL(form->getLeftSF())); /***** EG? *****/
}
else if (oper == RSCTL_EU_ACT)
{
return statesEUctx(
form->getActionsBDD(),
getStatesRSCTL(form->getLeftSF()),
getStatesRSCTL(form->getRightSF())
);
}
else if (oper == RSCTL_EF_ACT)
{
return statesEFctx(form->getActionsBDD(), getStatesRSCTL(form->getLeftSF()));
}
else if (oper == RSCTL_AX_ACT)
{
return !getPreEctx(!getStatesRSCTL(form->getLeftSF()) * *reach, form->getActionsBDD()) * *reach;
}
else if (oper == RSCTL_AG_ACT)
{
return !statesEFctx(form->getActionsBDD(),
!getStatesRSCTL(form->getLeftSF()) * *reach) * *reach;
}
else if (oper == RSCTL_AU_ACT)
{
BDD ng = !getStatesRSCTL(form->getRightSF()) * *reach;
BDD nf = !getStatesRSCTL(form->getLeftSF()) * *reach;
BDD x = !statesEUctx(form->getActionsBDD(), ng, ng * nf) * *reach; if (!x.IsZero()) {
if (!x.IsZero()) x = x * !statesEG(ng) * *reach;
x = x * !statesEGctx(form->getActionsBDD(), ng) * *reach;
return x;
}
else if (oper == RSCTL_AF_ACT)
{
return !statesEGctx(form->getActionsBDD(),
!getStatesRSCTL(form->getLeftSF()) * *reach) * *reach;
} }
assert(0); // Should never happen return x;
return BDD_FALSE; }
else if (oper == RSCTL_AF) {
return !statesEG(
!getStatesRSCTL(form->getLeftSF()) * *reach) * *reach;
}
/***** CONTEXT RESTRICTIONS: ******/
else if (oper == RSCTL_EX_ACT) {
return getPreEctx(getStatesRSCTL(form->getLeftSF()),
form->getActionsBDD()) * *reach;
}
else if (oper == RSCTL_EG_ACT) {
return statesEGctx(form->getActionsBDD(),
getStatesRSCTL(form->getLeftSF())); /***** EG? *****/
}
else if (oper == RSCTL_EU_ACT) {
return statesEUctx(
form->getActionsBDD(),
getStatesRSCTL(form->getLeftSF()),
getStatesRSCTL(form->getRightSF())
);
}
else if (oper == RSCTL_EF_ACT) {
return statesEFctx(form->getActionsBDD(), getStatesRSCTL(form->getLeftSF()));
}
else if (oper == RSCTL_AX_ACT) {
return !getPreEctx(!getStatesRSCTL(form->getLeftSF()) * *reach,
form->getActionsBDD()) * *reach;
}
else if (oper == RSCTL_AG_ACT) {
return !statesEFctx(form->getActionsBDD(),
!getStatesRSCTL(form->getLeftSF()) * *reach) * *reach;
}
else if (oper == RSCTL_AU_ACT) {
BDD ng = !getStatesRSCTL(form->getRightSF()) * *reach;
BDD nf = !getStatesRSCTL(form->getLeftSF()) * *reach;
BDD x = !statesEUctx(form->getActionsBDD(), ng, ng * nf) * *reach;
if (!x.IsZero()) {
x = x * !statesEGctx(form->getActionsBDD(), ng) * *reach;
}
return x;
}
else if (oper == RSCTL_AF_ACT) {
return !statesEGctx(form->getActionsBDD(),
!getStatesRSCTL(form->getLeftSF()) * *reach) * *reach;
}
assert(0); // Should never happen
return BDD_FALSE;
} }
BDD ModelChecker::statesEG(const BDD &states) BDD ModelChecker::statesEG(const BDD &states)
{ {
BDD x = states; BDD x = states;
BDD x_p = cuddMgr->bddZero(); BDD x_p = cuddMgr->bddZero();
while (x != x_p)
{ while (x != x_p) {
x_p = x; x_p = x;
x = x * getPreE(x); x = x * getPreE(x);
} }
return x;
return x;
} }
BDD ModelChecker::statesEU(const BDD &statesA, const BDD &statesB) BDD ModelChecker::statesEU(const BDD &statesA, const BDD &statesB)
{ {
BDD x = statesA; BDD x = statesA;
BDD x_p = *reach; BDD x_p = *reach;
while (x != x_p)
{ while (x != x_p) {
x_p = x; x_p = x;
x = x + (statesA * getPreE(x)); x = x + (statesA * getPreE(x));
} }
return x;
return x;
} }
BDD ModelChecker::statesEF(const BDD &states) BDD ModelChecker::statesEF(const BDD &states)
{ {
BDD x = states; BDD x = states;
BDD x_p = *reach; BDD x_p = *reach;
while (x != x_p)
{ while (x != x_p) {
x_p = x; x_p = x;
x = x + (*reach * getPreE(x)); x = x + (*reach * getPreE(x));
} }
return x;
return x;
} }
BDD ModelChecker::statesEGctx(const BDD *contexts, const BDD &states) BDD ModelChecker::statesEGctx(const BDD *contexts, const BDD &states)
{ {
BDD x = states; BDD x = states;
BDD x_p = cuddMgr->bddZero(); BDD x_p = cuddMgr->bddZero();
while (x != x_p)
{ while (x != x_p) {
x_p = x; x_p = x;
x = x * getPreEctx(x, contexts); x = x * getPreEctx(x, contexts);
} }
return x;
return x;
} }
BDD ModelChecker::statesEUctx(const BDD *contexts, const BDD &statesA, const BDD &statesB) BDD ModelChecker::statesEUctx(const BDD *contexts, const BDD &statesA,
const BDD &statesB)
{ {
BDD x = statesA; BDD x = statesA;
BDD x_p = *reach; BDD x_p = *reach;
while (x != x_p)
{ while (x != x_p) {
x_p = x; x_p = x;
x = x + (statesA * getPreEctx(x, contexts)); x = x + (statesA * getPreEctx(x, contexts));
} }
return x;
return x;
} }
BDD ModelChecker::statesEFctx(const BDD *contexts, const BDD &states) BDD ModelChecker::statesEFctx(const BDD *contexts, const BDD &states)
{ {
BDD x = states; BDD x = states;
BDD x_p = *reach; BDD x_p = *reach;
while (x != x_p)
{ while (x != x_p) {
x_p = x; x_p = x;
x = x + (*reach * getPreEctx(x, contexts)); x = x + (*reach * getPreEctx(x, contexts));
} }
return x;
return x;
} }
bool ModelChecker::checkRSCTL(FormRSCTL *form) bool ModelChecker::checkRSCTL(FormRSCTL *form)
{ {
if (form->isERSCTL()) if (form->isERSCTL()) {
return checkRSCTLbmc(form); return checkRSCTLbmc(form);
else }
return checkRSCTLfull(form); else {
return checkRSCTLfull(form);
}
} }
bool ModelChecker::checkRSCTLfull(FormRSCTL *form) bool ModelChecker::checkRSCTLfull(FormRSCTL *form)
{ {
if (opts->measure) if (opts->measure) {
opts->ver_time = cpuTime(); opts->ver_time = cpuTime();
}
assert(form != nullptr); assert(form != nullptr);
bool result = false; bool result = false;
VERB("Model checking for RSCTL formula: " << form->toStr()); VERB("Model checking for RSCTL formula: " << form->toStr());
VERB("Processing the formula: encoding entities"); VERB("Processing the formula: encoding entities");
form->encodeEntities(srs); form->encodeEntities(srs);
VERB("Entities encoded"); VERB("Entities encoded");
VERB("Processing the formula: encoding actions/contexts"); VERB("Processing the formula: encoding actions/contexts");
form->encodeActions(srs); form->encodeActions(srs);
VERB("Contexts encoded"); VERB("Contexts encoded");
assert(reach == nullptr); assert(reach == nullptr);
reach = new BDD(*initStates); reach = new BDD(*initStates);
BDD reach_p = cuddMgr->bddZero(); BDD reach_p = cuddMgr->bddZero();
VERB("Generating state space"); VERB("Generating state space");
unsigned int k = 0; unsigned int k = 0;
while (*reach != reach_p) while (*reach != reach_p) {
{
if (opts->show_progress) if (opts->show_progress) {
{ cout << "\rIteration " << ++k << flush;
cout << "\rIteration " << ++k << flush;
}
if (opts->reorder_reach)
{
VERB_L2("Reordering")
Cudd_ReduceHeap(cuddMgr->getManager(), CUDD_REORDER_SIFT, 10000);
}
reach_p = *reach;
*reach += getSucc(*reach);
} }
if (opts->show_progress) cout << endl; if (opts->reorder_reach) {
VERB_L2("Reordering")
VERB("Checking the formula"); Cudd_ReduceHeap(cuddMgr->getManager(), CUDD_REORDER_SIFT, 10000);
//if (*initStates * getStatesRSCTL(form) != cuddMgr->bddZero())
if (*initStates * getStatesRSCTL(form) == *initStates)
{
result = true;
}
else
{
result = false;
} }
cleanup(); reach_p = *reach;
*reach += getSucc(*reach);
}
cout << "Formula " << form->toStr() << (result ? " holds" : " does not hold") << endl; if (opts->show_progress) {
cout << endl;
}
if (opts->measure) VERB("Checking the formula");
{
opts->ver_time = cpuTime() - opts->ver_time;
opts->ver_mem = memUsed();
}
return result; //if (*initStates * getStatesRSCTL(form) != cuddMgr->bddZero())
if (*initStates * getStatesRSCTL(form) == *initStates) {
result = true;
}
else {
result = false;
}
cleanup();
cout << "Formula " << form->toStr() << (result ? " holds" : " does not hold")
<< endl;
if (opts->measure) {
opts->ver_time = cpuTime() - opts->ver_time;
opts->ver_mem = memUsed();
}
return result;
} }
bool ModelChecker::checkRSCTLbmc(FormRSCTL *form) bool ModelChecker::checkRSCTLbmc(FormRSCTL *form)
{ {
if (opts->measure) if (opts->measure) {
opts->ver_time = cpuTime(); opts->ver_time = cpuTime();
}
assert(form != nullptr); assert(form != nullptr);
if (!form->isERSCTL()) if (!form->isERSCTL()) {
{ FERROR("Formula " << form->toStr() <<
FERROR("Formula " << form->toStr() << " is not syntactically an ERSCTL formula"); " is not syntactically an ERSCTL formula");
}
bool result = false;
VERB("Bounded model checking for RSCTL formula: " << form->toStr());
VERB("Processing the formula: encoding entities");
form->encodeEntities(srs);
VERB("Entities encoded");
VERB("Processing the formula: encoding actions/contexts");
form->encodeActions(srs);
VERB("Contexts encoded");
assert(reach == nullptr);
reach = new BDD(*initStates);
BDD reach_p = cuddMgr->bddZero();
unsigned int k = 0;
while (*reach != reach_p) {
if (opts->show_progress) {
cout << "\rIteration " << ++k << flush;
} }
bool result = false; //if (*initStates * getStatesRSCTL(form) != cuddMgr->bddZero())
if (*initStates * getStatesRSCTL(form) == *initStates) {
VERB("Bounded model checking for RSCTL formula: " << form->toStr()); result = true;
break;
VERB("Processing the formula: encoding entities");
form->encodeEntities(srs);
VERB("Entities encoded");
VERB("Processing the formula: encoding actions/contexts");
form->encodeActions(srs);
VERB("Contexts encoded");
assert(reach == nullptr);
reach = new BDD(*initStates);
BDD reach_p = cuddMgr->bddZero();
unsigned int k = 0;
while (*reach != reach_p)
{
if (opts->show_progress)
{
cout << "\rIteration " << ++k << flush;
}
//if (*initStates * getStatesRSCTL(form) != cuddMgr->bddZero())
if (*initStates * getStatesRSCTL(form) == *initStates)
{
result = true;
break;
}
reach_p = *reach;
*reach += getSucc(*reach);
} }
if (opts->show_progress) cout << endl; reach_p = *reach;
*reach += getSucc(*reach);
}
cleanup(); if (opts->show_progress) {
cout << endl;
}
cout << "Formula " << form->toStr() << " " << (result ? "holds" : "does not hold") << endl; cleanup();
if (opts->measure) cout << "Formula " << form->toStr() << " " << (result ? "holds" :
{ "does not hold") << endl;
opts->ver_time = cpuTime() - opts->ver_time;
opts->ver_mem = memUsed();
}
return result; if (opts->measure) {
opts->ver_time = cpuTime() - opts->ver_time;
opts->ver_mem = memUsed();
}
return result;
} }
void ModelChecker::cleanup(void) void ModelChecker::cleanup(void)
{ {
delete reach; delete reach;
reach = nullptr; reach = nullptr;
} }
/** EOF **/ /** EOF **/

16
mc.hh
View File

@@ -30,12 +30,12 @@ class ModelChecker
vector<BDD> *trp; vector<BDD> *trp;
BDD *trm; BDD *trm;
// Context Automaton // Context Automaton
bool using_ctx_aut; bool using_ctx_aut;
vector<BDD> *pv_ca; vector<BDD> *pv_ca;
vector<BDD> *pv_ca_succ; vector<BDD> *pv_ca_succ;
BDD *pv_ca_E; BDD *pv_ca_E;
BDD *pv_ca_succ_E; BDD *pv_ca_succ_E;
unsigned int trp_size; unsigned int trp_size;
unsigned int totalStateVars; unsigned int totalStateVars;
@@ -43,7 +43,7 @@ class ModelChecker
/** /**
* @brief Abstracts away (in-place!) the context automaton states * @brief Abstracts away (in-place!) the context automaton states
*/ */
void dropCtxAutStatePart(BDD &states); void dropCtxAutStatePart(BDD &states);
BDD getSucc(const BDD &states); BDD getSucc(const BDD &states);
BDD getPreE(const BDD &states); BDD getPreE(const BDD &states);
@@ -57,7 +57,7 @@ class ModelChecker
BDD statesEFctx(const BDD *contexts, const BDD &states); BDD statesEFctx(const BDD *contexts, const BDD &states);
void cleanup(void); void cleanup(void);
public: public:
ModelChecker(SymRS *srs, Options *opts); ModelChecker(SymRS *srs, Options *opts);
void printReach(void); void printReach(void);

View File

@@ -29,39 +29,42 @@ typedef long long int64;
static inline double cpuTime(void) static inline double cpuTime(void)
{ {
struct rusage ru; struct rusage ru;
getrusage(RUSAGE_SELF, &ru); getrusage(RUSAGE_SELF, &ru);
return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000;
} }
static inline int memReadStat(void) static inline int memReadStat(void)
{ {
char name[256]; char name[256];
pid_t pid = getpid(); pid_t pid = getpid();
sprintf(name, "/proc/%d/statm", pid); sprintf(name, "/proc/%d/statm", pid);
FILE* in = fopen(name, "rb"); FILE *in = fopen(name, "rb");
if (in == nullptr)
{ if (in == nullptr) {
return 0; return 0;
}
int value;
for (int field = 0; field >= 0; --field) {
if (fscanf(in, "%d", &value) == EOF) {
FERROR("EOF");
} }
int value; }
for (int field = 0; field >= 0; --field)
{ fclose(in);
if (fscanf(in, "%d", &value) == EOF) return value;
FERROR("EOF");
}
fclose(in);
return value;
} }
static inline int64 memUsedInt64() static inline int64 memUsedInt64()
{ {
return (int64)memReadStat() * (int64)getpagesize(); return (int64)memReadStat() * (int64)getpagesize();
} }
static inline double memUsed() static inline double memUsed()
{ {
return memUsedInt64() / 1048576.0; return memUsedInt64() / 1048576.0;
} }
#endif #endif

View File

@@ -1,9 +1,10 @@
#ifndef RS_OPTIONS_HH #ifndef RS_OPTIONS_HH
#define RS_OPTIONS_HH #define RS_OPTIONS_HH
class Options { class Options
{
public: public:
unsigned int verbose; unsigned int verbose;
bool show_progress; bool show_progress;
bool measure; bool measure;
@@ -18,19 +19,19 @@ public:
Options(void) Options(void)
{ {
verbose = 0; verbose = 0;
show_progress = false; show_progress = false;
measure = false; measure = false;
part_tr_rel = false; part_tr_rel = false;
reorder_reach = false; reorder_reach = false;
reorder_trans = false; reorder_trans = false;
enc_time = 0; enc_time = 0;
enc_mem = 0; enc_mem = 0;
ver_time = 0; ver_time = 0;
ver_mem = 0; ver_mem = 0;
} }
}; };

345
rs.cc
View File

@@ -9,299 +9,320 @@
#include "rs.hh" #include "rs.hh"
RctSys::RctSys(void) RctSys::RctSys(void)
: current_process_defined(false) : current_process_defined(false)
{ {
ctx_aut = nullptr; ctx_aut = nullptr;
} }
bool RctSys::hasEntity(std::string name) bool RctSys::hasEntity(std::string name)
{ {
if (entities_names.find(name) == entities_names.end()) if (entities_names.find(name) == entities_names.end()) {
return false; return false;
else }
return true; else {
return true;
}
} }
void RctSys::addEntity(std::string name) void RctSys::addEntity(std::string name)
{ {
if (!hasEntity(name)) if (!hasEntity(name)) {
{ Entity new_entity_id = entities_ids.size();
Entity new_entity_id = entities_ids.size();
VERB_L2("Adding entity: " << name << " index=" << new_entity_id); VERB_L2("Adding entity: " << name << " index=" << new_entity_id);
entities_ids.push_back(name); entities_ids.push_back(name);
entities_names[name] = new_entity_id; entities_names[name] = new_entity_id;
} }
} }
std::string RctSys::getEntityName(Entity entityID) std::string RctSys::getEntityName(Entity entityID)
{ {
if (entityID < entities_ids.size()) if (entityID < entities_ids.size()) {
return entities_ids[entityID]; return entities_ids[entityID];
else }
{ else {
FERROR("No such entity ID: " << entityID); FERROR("No such entity ID: " << entityID);
return "??"; return "??";
} }
} }
Entity RctSys::getEntityID(std::string name) Entity RctSys::getEntityID(std::string name)
{ {
if (!hasEntity(name)) if (!hasEntity(name)) {
{ FERROR("No such entity: " << name);
FERROR("No such entity: " << name); }
}
return entities_names[name]; return entities_names[name];
} }
void RctSys::setCurrentProcess(std::string processName) void RctSys::setCurrentProcess(std::string processName)
{ {
VERB_LN(2, "Current Process: " << processName); VERB_LN(2, "Current Process: " << processName);
if (!hasProcess(processName)) if (!hasProcess(processName)) {
{ addProcess(processName);
addProcess(processName); }
}
current_proc_id = getProcessID(processName); current_proc_id = getProcessID(processName);
current_process_defined = true; current_process_defined = true;
} }
void RctSys::addProcess(std::string processName) void RctSys::addProcess(std::string processName)
{ {
if (!hasProcess(processName)) if (!hasProcess(processName)) {
{ Process new_proc_id = processes_ids.size();
Process new_proc_id = processes_ids.size();
VERB_L2("Adding process: " << processName << " index=" << new_proc_id); VERB_L2("Adding process: " << processName << " index=" << new_proc_id);
processes_ids.push_back(processName); processes_ids.push_back(processName);
processes_names[processName] = new_proc_id; processes_names[processName] = new_proc_id;
// reactions for the new process // reactions for the new process
proc_reactions[new_proc_id] = Reactions(); proc_reactions[new_proc_id] = Reactions();
assert(proc_reactions.size() == new_proc_id+1); assert(proc_reactions.size() == new_proc_id + 1);
} }
} }
bool RctSys::hasProcess(std::string processName) bool RctSys::hasProcess(std::string processName)
{ {
if (processes_names.find(processName) == processes_names.end()) if (processes_names.find(processName) == processes_names.end()) {
return false; return false;
else }
return true; else {
return true;
}
} }
Process RctSys::getProcessID(std::string processName) Process RctSys::getProcessID(std::string processName)
{ {
if (!hasProcess(processName)) if (!hasProcess(processName)) {
{ FERROR("No such process: " << processName);
FERROR("No such process: " << processName); }
}
return processes_names[processName]; return processes_names[processName];
} }
std::string RctSys::getProcessName(Process processID) std::string RctSys::getProcessName(Process processID)
{ {
if (processID < processes_ids.size()) if (processID < processes_ids.size()) {
return processes_ids[processID]; return processes_ids[processID];
else }
{ else {
FERROR("No such process ID: " << processID); FERROR("No such process ID: " << processID);
} }
} }
void RctSys::pushReactant(std::string entityName) void RctSys::pushReactant(std::string entityName)
{ {
if (!hasEntity(entityName)) if (!hasEntity(entityName)) {
addEntity(entityName); addEntity(entityName);
tmpReactants.insert(getEntityID(entityName)); }
tmpReactants.insert(getEntityID(entityName));
} }
void RctSys::pushInhibitor(std::string entityName) void RctSys::pushInhibitor(std::string entityName)
{ {
if (!hasEntity(entityName)) if (!hasEntity(entityName)) {
addEntity(entityName); addEntity(entityName);
tmpInhibitors.insert(getEntityID(entityName)); }
tmpInhibitors.insert(getEntityID(entityName));
} }
void RctSys::pushProduct(std::string entityName) void RctSys::pushProduct(std::string entityName)
{ {
if (!hasEntity(entityName)) if (!hasEntity(entityName)) {
addEntity(entityName); addEntity(entityName);
tmpProducts.insert(getEntityID(entityName)); }
tmpProducts.insert(getEntityID(entityName));
} }
void RctSys::addReactionForCurrentProcess(Reaction reaction) void RctSys::addReactionForCurrentProcess(Reaction reaction)
{ {
if (!current_process_defined) if (!current_process_defined) {
{ FERROR("Internal error. Current process is not set!");
FERROR("Internal error. Current process is not set!"); }
}
proc_reactions[current_proc_id].push_back(reaction); proc_reactions[current_proc_id].push_back(reaction);
} }
void RctSys::commitReaction(void) void RctSys::commitReaction(void)
{ {
VERB_L3("Saving reaction"); VERB_L3("Saving reaction");
Reaction r; Reaction r;
r.rctt = tmpReactants; r.rctt = tmpReactants;
r.inhib = tmpInhibitors; r.inhib = tmpInhibitors;
r.prod = tmpProducts; r.prod = tmpProducts;
addReactionForCurrentProcess(r); addReactionForCurrentProcess(r);
tmpReactants.clear(); tmpReactants.clear();
tmpInhibitors.clear(); tmpInhibitors.clear();
tmpProducts.clear(); tmpProducts.clear();
} }
std::string RctSys::entitiesToStr(const Entities &entities) std::string RctSys::entitiesToStr(const Entities &entities)
{ {
std::string s = " "; std::string s = " ";
for (auto a = entities.begin(); a != entities.end(); ++a)
{ for (auto a = entities.begin(); a != entities.end(); ++a) {
s += entityToStr(*a) + " "; s += entityToStr(*a) + " ";
} }
return s;
return s;
} }
void RctSys::showReactions(void) void RctSys::showReactions(void)
{ {
cout << "# Reactions:" << endl; cout << "# Reactions:" << endl;
for (unsigned int proc_id = 0; proc_id < processes_ids.size(); ++proc_id) for (unsigned int proc_id = 0; proc_id < processes_ids.size(); ++proc_id) {
{ cout << endl;
cout << endl; cout << " . proc = \"" << getProcessName(proc_id) << "\":" << endl;
cout << " . proc = \"" << getProcessName(proc_id) << "\":" << endl;
for (const auto &r : proc_reactions[proc_id]) for (const auto &r : proc_reactions[proc_id]) {
{ cout << " * (R={" << entitiesToStr(r.rctt) << "},"
cout << " * (R={" << entitiesToStr(r.rctt) << "}," << "I={" << entitiesToStr(r.inhib) << "},"
<< "I={" << entitiesToStr(r.inhib) << "}," << "P={" << entitiesToStr(r.prod) << "})" << endl;
<< "P={" << entitiesToStr(r.prod) << "})" << endl; }
} }
}
cout << endl; cout << endl;
} }
void RctSys::pushStateEntity(std::string entityName) void RctSys::pushStateEntity(std::string entityName)
{ {
if (!hasEntity(entityName)) if (!hasEntity(entityName)) {
{ FERROR("No such entity: " << entityName);
FERROR("No such entity: " << entityName); }
}
tmpState.insert(getEntityID(entityName)); tmpState.insert(getEntityID(entityName));
} }
void RctSys::commitInitState(void) void RctSys::commitInitState(void)
{ {
if (ctx_aut != nullptr) if (ctx_aut != nullptr) {
{ FERROR("Initial RS states must not be used with context automaton");
FERROR("Initial RS states must not be used with context automaton"); }
}
initStates.insert(tmpState); initStates.insert(tmpState);
tmpState.clear(); tmpState.clear();
} }
void RctSys::addActionEntity(std::string entityName) void RctSys::addActionEntity(std::string entityName)
{ {
if (!hasEntity(entityName)) if (!hasEntity(entityName)) {
addEntity(entityName); addEntity(entityName);
actionEntities.insert(getEntityID(entityName)); }
actionEntities.insert(getEntityID(entityName));
} }
void RctSys::addActionEntity(Entity entity) void RctSys::addActionEntity(Entity entity)
{ {
if (!isActionEntity(entity)) if (!isActionEntity(entity)) {
actionEntities.insert(entity); actionEntities.insert(entity);
}
} }
bool RctSys::isActionEntity(Entity entity) bool RctSys::isActionEntity(Entity entity)
{ {
if (actionEntities.count(entity) > 0) if (actionEntities.count(entity) > 0) {
return true; return true;
else }
return false; else {
return false;
}
} }
void RctSys::showActionEntities(void) void RctSys::showActionEntities(void)
{ {
cout << "# Context entities:"; cout << "# Context entities:";
for (auto a = actionEntities.begin(); a != actionEntities.end(); ++a)
{ for (auto a = actionEntities.begin(); a != actionEntities.end(); ++a) {
cout << " " << getEntityName(*a); cout << " " << getEntityName(*a);
} }
cout << endl;
cout << endl;
} }
void RctSys::showInitialStates(void) void RctSys::showInitialStates(void)
{ {
cout << "# Initial states:" << endl; cout << "# Initial states:" << endl;
for (auto s = initStates.begin(); s != initStates.end(); ++s)
{ for (auto s = initStates.begin(); s != initStates.end(); ++s) {
cout << " *"; cout << " *";
for (auto a = s->begin(); a != s->end(); ++a)
{ for (auto a = s->begin(); a != s->end(); ++a) {
cout << " " << getEntityName(*a); cout << " " << getEntityName(*a);
}
cout << endl;
} }
cout << endl;
}
} }
void RctSys::printSystem(void) void RctSys::printSystem(void)
{ {
if (!usingContextAutomaton()) if (!usingContextAutomaton()) {
showInitialStates(); showInitialStates();
showActionEntities(); }
showReactions();
if (ctx_aut != nullptr) ctx_aut->printAutomaton(); showActionEntities();
showReactions();
if (ctx_aut != nullptr) {
ctx_aut->printAutomaton();
}
} }
void RctSys::ctxAutEnable(void) void RctSys::ctxAutEnable(void)
{ {
assert(ctx_aut == nullptr); assert(ctx_aut == nullptr);
if (initStatesDefined())
{ if (initStatesDefined()) {
FERROR("Initial states must not be defined if using context automaton"); FERROR("Initial states must not be defined if using context automaton");
} }
ctx_aut = new CtxAut(opts, this);
ctx_aut = new CtxAut(opts, this);
} }
void RctSys::ctxAutAddState(std::string stateName) void RctSys::ctxAutAddState(std::string stateName)
{ {
assert(ctx_aut != nullptr); assert(ctx_aut != nullptr);
ctx_aut->addState(stateName); ctx_aut->addState(stateName);
} }
void RctSys::ctxAutSetInitState(std::string stateName) void RctSys::ctxAutSetInitState(std::string stateName)
{ {
assert(ctx_aut != nullptr); assert(ctx_aut != nullptr);
ctx_aut->setInitState(stateName); ctx_aut->setInitState(stateName);
} }
void RctSys::ctxAutAddTransition(std::string srcStateName, std::string dstStateName) void RctSys::ctxAutAddTransition(std::string srcStateName,
std::string dstStateName)
{ {
assert(ctx_aut != nullptr); assert(ctx_aut != nullptr);
ctx_aut->addTransition(srcStateName, dstStateName); ctx_aut->addTransition(srcStateName, dstStateName);
} }
void RctSys::ctxAutPushNamedContextEntity(std::string entityName) void RctSys::ctxAutPushNamedContextEntity(std::string entityName)
{ {
assert(ctx_aut != nullptr); assert(ctx_aut != nullptr);
Entity entity_id = getEntityID(entityName); Entity entity_id = getEntityID(entityName);
// //
// We mark the entity as an action entity // We mark the entity as an action entity
// //
// This step is required to ensure the minimal number of // This step is required to ensure the minimal number of
// BDD variables used in the encoding of the context sets // BDD variables used in the encoding of the context sets
// //
addActionEntity(entity_id); addActionEntity(entity_id);
ctx_aut->pushContextEntity(entity_id); ctx_aut->pushContextEntity(entity_id);
} }
/** EOF **/ /** EOF **/

140
rs.hh
View File

@@ -28,82 +28,106 @@ class CtxAut;
class RctSys class RctSys
{ {
friend class SymRS; friend class SymRS;
friend class SymRSstate; friend class SymRSstate;
public: public:
RctSys(void); RctSys(void);
void setOptions(Options *opts) { this->opts = opts; } void setOptions(Options *opts)
bool hasEntity(std::string entityName); {
void addEntity(std::string entityName); this->opts = opts;
std::string getEntityName(Entity entityID); }
bool hasEntity(std::string entityName);
void addEntity(std::string entityName);
std::string getEntityName(Entity entityID);
void setCurrentProcess(std::string processName); void setCurrentProcess(std::string processName);
void addProcess(std::string processName); void addProcess(std::string processName);
bool hasProcess(std::string processName); bool hasProcess(std::string processName);
Process getProcessID(std::string processName); Process getProcessID(std::string processName);
std::string getProcessName(Process processID); std::string getProcessName(Process processID);
void addReactionForCurrentProcess(Reaction reaction); void addReactionForCurrentProcess(Reaction reaction);
void pushReactant(std::string entityName); void pushReactant(std::string entityName);
void pushInhibitor(std::string entityName); void pushInhibitor(std::string entityName);
void pushProduct(std::string entityName); void pushProduct(std::string entityName);
void commitReaction(void); void commitReaction(void);
std::string entityToStr(const Entity entity) { return entities_ids[entity]; } std::string entityToStr(const Entity entity)
std::string entitiesToStr(const Entities &entities); {
void showReactions(void); return entities_ids[entity];
void pushStateEntity(std::string entityName); }
void commitInitState(void); std::string entitiesToStr(const Entities &entities);
void addActionEntity(std::string entityName); void showReactions(void);
void addActionEntity(Entity entity); void pushStateEntity(std::string entityName);
bool isActionEntity(Entity entity); void commitInitState(void);
void resetInitStates(void) { initStates.clear(); } void addActionEntity(std::string entityName);
unsigned int getEntitiesSize(void) { return entities_ids.size(); } void addActionEntity(Entity entity);
unsigned int getReactionsSize(void) { return reactions.size(); } bool isActionEntity(Entity entity);
unsigned int getActionsSize(void) { return actionEntities.size(); } void resetInitStates(void)
void showInitialStates(void); {
void showActionEntities(void); initStates.clear();
void printSystem(void); }
unsigned int getEntitiesSize(void)
{
return entities_ids.size();
}
unsigned int getReactionsSize(void)
{
return reactions.size();
}
unsigned int getActionsSize(void)
{
return actionEntities.size();
}
void showInitialStates(void);
void showActionEntities(void);
void printSystem(void);
void ctxAutEnable(void); void ctxAutEnable(void);
void ctxAutAddState(std::string stateName); void ctxAutAddState(std::string stateName);
void ctxAutSetInitState(std::string stateName); void ctxAutSetInitState(std::string stateName);
void ctxAutAddTransition(std::string srcStateName, std::string dstStateName); void ctxAutAddTransition(std::string srcStateName, std::string dstStateName);
void ctxAutPushNamedContextEntity(std::string entity_name); void ctxAutPushNamedContextEntity(std::string entity_name);
bool initStatesDefined(void) { return initStates.size() != 0; } bool initStatesDefined(void)
bool usingContextAutomaton(void) { return ctx_aut != nullptr; } {
return initStates.size() != 0;
}
bool usingContextAutomaton(void)
{
return ctx_aut != nullptr;
}
private: private:
Reactions reactions; // TODO: to be removed later Reactions reactions; // TODO: to be removed later
ReactionsForProc proc_reactions; ReactionsForProc proc_reactions;
EntitiesSets initStates; EntitiesSets initStates;
Entities actionEntities; Entities actionEntities;
CtxAut *ctx_aut; CtxAut *ctx_aut;
EntitiesById entities_ids; EntitiesById entities_ids;
EntitiesByName entities_names; EntitiesByName entities_names;
ProcessesById processes_ids; ProcessesById processes_ids;
ProcessesByName processes_names; ProcessesByName processes_names;
Process current_proc_id; Process current_proc_id;
bool current_process_defined; bool current_process_defined;
Entities tmpReactants; Entities tmpReactants;
Entities tmpInhibitors; Entities tmpInhibitors;
Entities tmpProducts; Entities tmpProducts;
Entities tmpState; Entities tmpState;
Options *opts; Options *opts;
Entity getEntityID(std::string entityName); Entity getEntityID(std::string entityName);
}; };

View File

@@ -2,61 +2,60 @@
#include "rsin_parser.hh" #include "rsin_parser.hh"
rsin_driver::rsin_driver(void) rsin_driver::rsin_driver(void)
: trace_scanning(false), trace_parsing(false) : trace_scanning(false), trace_parsing(false)
{ {
initialise(); initialise();
} }
rsin_driver::rsin_driver(RctSys *rs) rsin_driver::rsin_driver(RctSys *rs)
: trace_scanning(false), trace_parsing(false) : trace_scanning(false), trace_parsing(false)
{ {
initialise(); initialise();
this->rs = rs; this->rs = rs;
} }
void rsin_driver::initialise(void) void rsin_driver::initialise(void)
{ {
rs = nullptr; rs = nullptr;
rsctlform = nullptr; rsctlform = nullptr;
opts = nullptr; opts = nullptr;
use_ctx_aut = false; use_ctx_aut = false;
use_concentrations = false; use_concentrations = false;
} }
rsin_driver::~rsin_driver () rsin_driver::~rsin_driver ()
{ {
// placeholder // placeholder
} }
int rsin_driver::parse(const std::string &f) int rsin_driver::parse(const std::string &f)
{ {
file = f; file = f;
scan_begin(); scan_begin();
yy::rsin_parser parser(*this); yy::rsin_parser parser(*this);
parser.set_debug_level(trace_parsing); parser.set_debug_level(trace_parsing);
int res = parser.parse(); int res = parser.parse();
scan_end(); scan_end();
return res; return res;
} }
void rsin_driver::error(const yy::location &l, const std::string &m) void rsin_driver::error(const yy::location &l, const std::string &m)
{ {
std::cerr << l << ": " << m << std::endl; std::cerr << l << ": " << m << std::endl;
} }
void rsin_driver::error(const std::string &m) void rsin_driver::error(const std::string &m)
{ {
std::cerr << m << std::endl; std::cerr << m << std::endl;
} }
FormRSCTL *rsin_driver::getFormRSCTL(void) FormRSCTL *rsin_driver::getFormRSCTL(void)
{ {
if (rsctlform == nullptr) if (rsctlform == nullptr) {
{ FERROR("RSCTL formula was not supplied!");
FERROR("RSCTL formula was not supplied!"); }
}
return rsctlform; return rsctlform;
} }
// //
@@ -64,40 +63,40 @@ FormRSCTL *rsin_driver::getFormRSCTL(void)
// //
void rsin_driver::ensureOptionsAllowed(void) void rsin_driver::ensureOptionsAllowed(void)
{ {
if (rs != nullptr) if (rs != nullptr) {
{ FERROR("Options cannot be set/modified after the reaction system is initialised")
FERROR("Options cannot be set/modified after the reaction system is initialised") }
}
} }
void rsin_driver::ensureReactionSystemReady(void) void rsin_driver::ensureReactionSystemReady(void)
{ {
if (rs == nullptr) if (rs == nullptr) {
setupReactionSystem(); setupReactionSystem();
}
} }
void rsin_driver::setupReactionSystem(void) void rsin_driver::setupReactionSystem(void)
{ {
assert(rs == nullptr); assert(rs == nullptr);
rs = new RctSys; rs = new RctSys;
if (use_ctx_aut) VERB("Using RS with CA") if (use_ctx_aut) VERB("Using RS with CA")
else VERB("Using ordinary RS") else VERB("Using ordinary RS")
rs->setOptions(opts); rs->setOptions(opts);
} }
RctSys *rsin_driver::getReactionSystem(void) RctSys *rsin_driver::getReactionSystem(void)
{ {
ensureReactionSystemReady(); ensureReactionSystemReady();
assert(rs != nullptr); assert(rs != nullptr);
return rs; return rs;
} }
void rsin_driver::useContextAutomaton(void) void rsin_driver::useContextAutomaton(void)
{ {
ensureOptionsAllowed(); ensureOptionsAllowed();
use_ctx_aut = true; use_ctx_aut = true;
getReactionSystem()->ctxAutEnable(); getReactionSystem()->ctxAutEnable();
} }

View File

@@ -19,7 +19,7 @@ YY_DECL;
// Conducting the whole scanning an parsing of RS // Conducting the whole scanning an parsing of RS
class rsin_driver class rsin_driver
{ {
public: public:
rsin_driver(void); rsin_driver(void);
rsin_driver(RctSys *rs); rsin_driver(RctSys *rs);
virtual ~rsin_driver(); virtual ~rsin_driver();
@@ -28,9 +28,9 @@ public:
FormRSCTL *rsctlform; FormRSCTL *rsctlform;
Options *opts; Options *opts;
// options in configuration file: // options in configuration file:
bool use_ctx_aut; bool use_ctx_aut;
bool use_concentrations; bool use_concentrations;
// Handling the scanner // Handling the scanner
void scan_begin(); void scan_begin();
@@ -41,28 +41,38 @@ public:
std::string file; std::string file;
bool trace_parsing; bool trace_parsing;
void setOptions(Options *opts) { this->opts = opts; }; void setOptions(Options *opts)
void addFormRSCTL(FormRSCTL *f) { rsctlform = f; }; {
this->opts = opts;
};
void addFormRSCTL(FormRSCTL *f)
{
rsctlform = f;
};
FormRSCTL *getFormRSCTL(void); FormRSCTL *getFormRSCTL(void);
void ensureOptionsAllowed(void); void ensureOptionsAllowed(void);
void useContextAutomaton(void); void useContextAutomaton(void);
void useConcentrations(void) { ensureOptionsAllowed(); use_concentrations = true; }; void useConcentrations(void)
{
ensureOptionsAllowed();
use_concentrations = true;
};
void ensureReactionSystemReady(void); void ensureReactionSystemReady(void);
void setupReactionSystem(void); void setupReactionSystem(void);
RctSys *getReactionSystem(void); RctSys *getReactionSystem(void);
CtxAut *getCtxAut(void); CtxAut *getCtxAut(void);
// Error handling. // Error handling.
void error(const yy::location &l, const std::string &m); void error(const yy::location &l, const std::string &m);
void error(const std::string &m); void error(const std::string &m);
private: private:
RctSys *rs; RctSys *rs;
void initialise(void); void initialise(void);
}; };
#endif #endif

790
symrs.cc
View File

@@ -8,593 +8,583 @@
SymRS::SymRS(RctSys *rs, Options *opts) SymRS::SymRS(RctSys *rs, Options *opts)
{ {
this->rs = rs; this->rs = rs;
this->opts = opts; this->opts = opts;
totalRctSysStateVars = rs->getEntitiesSize(); totalRctSysStateVars = rs->getEntitiesSize();
totalReactions = rs->getReactionsSize(); totalReactions = rs->getReactionsSize();
totalActions = rs->getActionsSize(); totalActions = rs->getActionsSize();
totalCtxAutStateVars = getCtxAutStateEncodingSize(); totalCtxAutStateVars = getCtxAutStateEncodingSize();
totalStateVars = totalRctSysStateVars + totalCtxAutStateVars; totalStateVars = totalRctSysStateVars + totalCtxAutStateVars;
partTrans = nullptr; partTrans = nullptr;
monoTrans = nullptr; monoTrans = nullptr;
pv_ca = nullptr; pv_ca = nullptr;
pv_ca_succ = nullptr; pv_ca_succ = nullptr;
tr_ca = nullptr; tr_ca = nullptr;
encode(); encode();
} }
BDD SymRS::encEntity_raw(Entity entity, bool succ) const BDD SymRS::encEntity_raw(Entity entity, bool succ) const
{ {
BDD r; BDD r;
if (succ) if (succ) {
r = (*pv_succ)[entity]; r = (*pv_succ)[entity];
else }
r = (*pv)[entity]; else {
r = (*pv)[entity];
}
return r; return r;
} }
BDD SymRS::encEntitiesConj_raw(const Entities &entities, bool succ) BDD SymRS::encEntitiesConj_raw(const Entities &entities, bool succ)
{ {
BDD r = BDD_TRUE; BDD r = BDD_TRUE;
for (const auto &entity : entities) for (const auto &entity : entities) {
{ if (succ) {
if (succ) r *= encEntitySucc(entity); r *= encEntitySucc(entity);
else r *= encEntity(entity);
} }
else {
r *= encEntity(entity);
}
}
return r; return r;
} }
BDD SymRS::encEntitiesDisj_raw(const Entities &entities, bool succ) BDD SymRS::encEntitiesDisj_raw(const Entities &entities, bool succ)
{ {
BDD r = BDD_FALSE; BDD r = BDD_FALSE;
for (const auto &entity : entities) for (const auto &entity : entities) {
{ if (succ) {
if (succ) r += encEntitySucc(entity); r += encEntitySucc(entity);
else r += encEntity(entity);
} }
else {
r += encEntity(entity);
}
}
return r; return r;
} }
BDD SymRS::encStateActEntitiesConj(const Entities &entities) BDD SymRS::encStateActEntitiesConj(const Entities &entities)
{ {
BDD r = BDD_TRUE; BDD r = BDD_TRUE;
for (const auto &entity : entities) for (const auto &entity : entities) {
{ BDD state_act = encEntity(entity);
BDD state_act = encEntity(entity); int actEntity;
int actEntity;
// if entity is also an action entity, we include it in the encoding // if entity is also an action entity, we include it in the encoding
if ((actEntity = getMappedStateToActID(entity)) >= 0) if ((actEntity = getMappedStateToActID(entity)) >= 0) {
state_act += encActEntity(actEntity); state_act += encActEntity(actEntity);
r *= state_act;
} }
return r; r *= state_act;
}
return r;
} }
BDD SymRS::encStateActEntitiesDisj(const Entities &entities) BDD SymRS::encStateActEntitiesDisj(const Entities &entities)
{ {
BDD r = BDD_FALSE; BDD r = BDD_FALSE;
for (const auto &entity : entities) for (const auto &entity : entities) {
{ BDD state_act = encEntity(entity);
BDD state_act = encEntity(entity); int actEntity;
int actEntity;
// if entity is also an aciton entity, we include it in the encoding // if entity is also an aciton entity, we include it in the encoding
if ((actEntity = getMappedStateToActID(entity)) >= 0) if ((actEntity = getMappedStateToActID(entity)) >= 0) {
state_act += encActEntity(actEntity); state_act += encActEntity(actEntity);
r += state_act;
} }
return r; r += state_act;
}
return r;
} }
BDD SymRS::encActEntitiesConj(const Entities &entities) BDD SymRS::encActEntitiesConj(const Entities &entities)
{ {
BDD r = BDD_TRUE; BDD r = BDD_TRUE;
for (const auto &entity : entities) for (const auto &entity : entities) {
{ Entity actEntity = getMappedStateToActID(entity);
Entity actEntity = getMappedStateToActID(entity); r *= encActEntity(actEntity);
r *= encActEntity(actEntity); }
}
return r; return r;
} }
BDD SymRS::compState(const BDD &state) const BDD SymRS::compState(const BDD &state) const
{ {
BDD s = state; BDD s = state;
for (unsigned int i = 0; i < totalRctSysStateVars; ++i) for (unsigned int i = 0; i < totalRctSysStateVars; ++i) {
{ if (!(*pv)[i] * state != cuddMgr->bddZero()) {
if (!(*pv)[i] * state != cuddMgr->bddZero()) s *= !(*pv)[i];
s *= !(*pv)[i];
} }
}
return s; return s;
} }
BDD SymRS::compContext(const BDD &context) const BDD SymRS::compContext(const BDD &context) const
{ {
BDD c = context; BDD c = context;
for (unsigned int i = 0; i < totalActions; ++i) for (unsigned int i = 0; i < totalActions; ++i) {
{ if (!(*pv_act)[i] * context != cuddMgr->bddZero()) {
if (!(*pv_act)[i] * context != cuddMgr->bddZero()) c *= !(*pv_act)[i];
c *= !(*pv_act)[i];
} }
}
return c; return c;
} }
std::string SymRS::decodedRctSysStateToStr(const BDD &state) std::string SymRS::decodedRctSysStateToStr(const BDD &state)
{ {
std::string s = "{ "; std::string s = "{ ";
for (unsigned int i = 0; i < totalRctSysStateVars; ++i)
{ for (unsigned int i = 0; i < totalRctSysStateVars; ++i) {
if (!(encEntity(i) * state).IsZero()) if (!(encEntity(i) * state).IsZero()) {
{ s += rs->entityToStr(i) + " ";
s += rs->entityToStr(i) + " ";
}
} }
s += "}"; }
return s;
s += "}";
return s;
} }
void SymRS::printDecodedRctSysStates(const BDD &states) void SymRS::printDecodedRctSysStates(const BDD &states)
{ {
BDD unproc = states; BDD unproc = states;
while (!unproc.IsZero())
{ while (!unproc.IsZero()) {
BDD t = unproc.PickOneMinterm(*pv_rs); BDD t = unproc.PickOneMinterm(*pv_rs);
cout << decodedRctSysStateToStr(t) << endl; cout << decodedRctSysStateToStr(t) << endl;
if (opts->verbose > 9) {
t.PrintMinterm(); if (opts->verbose > 9) {
cout << endl; t.PrintMinterm();
} cout << endl;
unproc -= t;
} }
unproc -= t;
}
} }
void SymRS::initBDDvars(void) void SymRS::initBDDvars(void)
{ {
VERB("Initialising CUDD"); VERB("Initialising CUDD");
cuddMgr = new Cudd(0,0); cuddMgr = new Cudd(0, 0);
VERB("Preparing BDD variables"); VERB("Preparing BDD variables");
// used for bddVar // used for bddVar
unsigned int bdd_var_idx = 0; unsigned int bdd_var_idx = 0;
// used for pv, pv_succ // used for pv, pv_succ
unsigned int global_state_idx = 0; unsigned int global_state_idx = 0;
// Variables for reaction system with CA (if used) // Variables for reaction system with CA (if used)
pv = new vector<BDD>(totalStateVars); pv = new vector<BDD>(totalStateVars);
pv_succ = new vector<BDD>(totalStateVars); pv_succ = new vector<BDD>(totalStateVars);
pv_E = new BDD(BDD_TRUE); pv_E = new BDD(BDD_TRUE);
pv_succ_E = new BDD(BDD_TRUE); pv_succ_E = new BDD(BDD_TRUE);
// Reaction system (no actions, no CA) // Reaction system (no actions, no CA)
pv_rs = new vector<BDD>(totalRctSysStateVars); pv_rs = new vector<BDD>(totalRctSysStateVars);
pv_rs_succ = new vector<BDD>(totalRctSysStateVars); pv_rs_succ = new vector<BDD>(totalRctSysStateVars);
pv_rs_E = new BDD(BDD_TRUE); pv_rs_E = new BDD(BDD_TRUE);
pv_rs_succ_E = new BDD(BDD_TRUE); pv_rs_succ_E = new BDD(BDD_TRUE);
for (unsigned int i = 0; i < totalRctSysStateVars; ++i) for (unsigned int i = 0; i < totalRctSysStateVars; ++i) {
{ (*pv_rs)[i] = cuddMgr->bddVar(bdd_var_idx++);
(*pv_rs)[i] = cuddMgr->bddVar(bdd_var_idx++); (*pv_rs_succ)[i] = cuddMgr->bddVar(bdd_var_idx++);
(*pv_rs_succ)[i] = cuddMgr->bddVar(bdd_var_idx++); *pv_rs_E *= (*pv_rs)[i];
*pv_rs_E *= (*pv_rs)[i]; *pv_rs_succ_E *= (*pv_rs_succ)[i];
*pv_rs_succ_E *= (*pv_rs_succ)[i];
(*pv)[global_state_idx] = (*pv_rs)[i]; (*pv)[global_state_idx] = (*pv_rs)[i];
(*pv_succ)[global_state_idx] = (*pv_rs_succ)[i]; (*pv_succ)[global_state_idx] = (*pv_rs_succ)[i];
++global_state_idx; ++global_state_idx;
} }
// CA // CA
if (usingContextAutomaton()) if (usingContextAutomaton()) {
{ VERB("Context automaton variables");
VERB("Context automaton variables");
pv_ca = new vector<BDD>(totalCtxAutStateVars); pv_ca = new vector<BDD>(totalCtxAutStateVars);
pv_ca_succ = new vector<BDD>(totalCtxAutStateVars); pv_ca_succ = new vector<BDD>(totalCtxAutStateVars);
pv_ca_E = new BDD(BDD_TRUE); pv_ca_E = new BDD(BDD_TRUE);
pv_ca_succ_E = new BDD(BDD_TRUE); pv_ca_succ_E = new BDD(BDD_TRUE);
for (unsigned int i = 0; i < totalCtxAutStateVars; ++i) for (unsigned int i = 0; i < totalCtxAutStateVars; ++i) {
{ (*pv_ca)[i] = cuddMgr->bddVar(bdd_var_idx++);
(*pv_ca)[i] = cuddMgr->bddVar(bdd_var_idx++); (*pv_ca_succ)[i] = cuddMgr->bddVar(bdd_var_idx++);
(*pv_ca_succ)[i] = cuddMgr->bddVar(bdd_var_idx++); *pv_ca_E *= (*pv_ca)[i];
*pv_ca_E *= (*pv_ca)[i]; *pv_ca_succ_E *= (*pv_ca_succ)[i];
*pv_ca_succ_E *= (*pv_ca_succ)[i];
(*pv)[global_state_idx] = (*pv_ca)[i]; (*pv)[global_state_idx] = (*pv_ca)[i];
(*pv_succ)[global_state_idx] = (*pv_ca_succ)[i]; (*pv_succ)[global_state_idx] = (*pv_ca_succ)[i];
++global_state_idx; ++global_state_idx;
}
}
// Actions/Contexts
pv_act = new vector<BDD>(totalActions);
pv_act_E = new BDD(BDD_TRUE);
for (unsigned int i = 0; i < totalActions; ++i)
{
(*pv_act)[i] = cuddMgr->bddVar(bdd_var_idx++);
*pv_act_E *= (*pv_act)[i];
} }
}
// Quantification BDDs // Actions/Contexts
pv_act = new vector<BDD>(totalActions);
pv_act_E = new BDD(BDD_TRUE);
*pv_E = *pv_rs_E; for (unsigned int i = 0; i < totalActions; ++i) {
*pv_succ_E = *pv_rs_succ_E; (*pv_act)[i] = cuddMgr->bddVar(bdd_var_idx++);
*pv_act_E *= (*pv_act)[i];
}
if (usingContextAutomaton()) // Quantification BDDs
{
*pv_E *= *pv_ca_E;
*pv_succ_E *= *pv_ca_succ_E;
}
VERB("All BDD variables ready"); *pv_E = *pv_rs_E;
*pv_succ_E = *pv_rs_succ_E;
if (usingContextAutomaton()) {
*pv_E *= *pv_ca_E;
*pv_succ_E *= *pv_ca_succ_E;
}
VERB("All BDD variables ready");
} }
void SymRS::encodeTransitions(void) void SymRS::encodeTransitions(void)
{ {
DecompReactions dr; DecompReactions dr;
VERB("Decomposing reactions"); VERB("Decomposing reactions");
for (unsigned int i = 0; i < totalReactions; ++i)
{
ReactionCond cond;
cond.rctt = rs->reactions[i].rctt;
cond.inhib = rs->reactions[i].inhib;
for (Entities::iterator p = rs->reactions[i].prod.begin(); for (unsigned int i = 0; i < totalReactions; ++i) {
p != rs->reactions[i].prod.end(); ++p) ReactionCond cond;
{ cond.rctt = rs->reactions[i].rctt;
dr[*p].push_back(cond); cond.inhib = rs->reactions[i].inhib;
}
for (Entities::iterator p = rs->reactions[i].prod.begin();
p != rs->reactions[i].prod.end(); ++p) {
dr[*p].push_back(cond);
}
}
VERB("Encoding reactions");
if (opts->part_tr_rel) {
VERB("Using partitioned transition relation encoding");
partTrans = new vector<BDD>(totalRctSysStateVars);
}
else {
VERB("Using monolithic transition relation encoding");
monoTrans = new BDD(BDD_TRUE);
}
for (unsigned int p = 0; p < totalRctSysStateVars; ++p) {
VERB_L3("Encoding for successor " << p);
DecompReactions::iterator di;
if ((di = dr.find(p)) == dr.end()) {
// there is no reaction producing p:
if (opts->part_tr_rel) {
(*partTrans)[p] = !encEntitySucc(p);
}
else {
*monoTrans *= !encEntitySucc(p);
}
}
else {
// di - reactions producing p
BDD conditions = BDD_FALSE;
assert(di->second.size() > 0);
for (unsigned int j = 0; j < di->second.size(); ++j) {
conditions += encStateActEntitiesConj(di->second[j].rctt) *
!encStateActEntitiesDisj(di->second[j].inhib);
}
if (opts->part_tr_rel) {
(*partTrans)[p] = conditions * encEntitySucc(p);
(*partTrans)[p] += !conditions * !encEntitySucc(p);
}
else {
*monoTrans *= (conditions * encEntitySucc(p)) + (!conditions * !encEntitySucc(
p));
}
} }
VERB("Encoding reactions"); if (opts->reorder_trans) {
VERB_L2("Reordering");
if (opts->part_tr_rel) Cudd_ReduceHeap(cuddMgr->getManager(), CUDD_REORDER_SIFT, 10000);
{
VERB("Using partitioned transition relation encoding");
partTrans = new vector<BDD>(totalRctSysStateVars);
}
else
{
VERB("Using monolithic transition relation encoding");
monoTrans = new BDD(BDD_TRUE);
} }
for (unsigned int p = 0; p < totalRctSysStateVars; ++p) }
{
VERB_L3("Encoding for successor " << p);
DecompReactions::iterator di; VERB("Reactions ready");
if ((di = dr.find(p)) == dr.end()) if (usingContextAutomaton()) {
{ VERB("Augmenting transition relation encoding with the transition relation for context automaton");
// there is no reaction producing p:
if (opts->part_tr_rel)
(*partTrans)[p] = !encEntitySucc(p);
else
{
*monoTrans *= !encEntitySucc(p);
}
}
else
{
// di - reactions producing p
BDD conditions = BDD_FALSE;
assert(di->second.size() > 0);
for (unsigned int j = 0; j < di->second.size(); ++j)
{
conditions += encStateActEntitiesConj(di->second[j].rctt) * !encStateActEntitiesDisj(di->second[j].inhib);
}
if (opts->part_tr_rel)
{
(*partTrans)[p] = conditions * encEntitySucc(p);
(*partTrans)[p] += !conditions * !encEntitySucc(p);
}
else
{
*monoTrans *= (conditions * encEntitySucc(p)) + (!conditions * !encEntitySucc(p));
}
}
if (opts->reorder_trans)
{
VERB_L2("Reordering");
Cudd_ReduceHeap(cuddMgr->getManager(), CUDD_REORDER_SIFT, 10000);
}
if (opts->part_tr_rel) {
assert(0);
} }
else {
assert(tr_ca != nullptr);
*monoTrans *= *tr_ca;
}
}
VERB("Reactions ready"); VERB("Transition relation encoded")
if (usingContextAutomaton())
{
VERB("Augmenting transition relation encoding with the transition relation for context automaton");
if (opts->part_tr_rel)
{
assert(0);
}
else
{
assert(tr_ca != nullptr);
*monoTrans *= *tr_ca;
}
}
VERB("Transition relation encoded")
} }
BDD SymRS::getEncState(const Entities &entities) BDD SymRS::getEncState(const Entities &entities)
{ {
assert(0); assert(0);
//BDD state = compState(encEntitiesConj(rs->initState)); //BDD state = compState(encEntitiesConj(rs->initState));
//for (RctSys::Entities::iterator at = rs->actionEntities.begin(); at != rs->actionEntities.end(); ++at) //for (RctSys::Entities::iterator at = rs->actionEntities.begin(); at != rs->actionEntities.end(); ++at)
//{ //{
// state = state.ExistAbstract(encEntity(*at)); // state = state.ExistAbstract(encEntity(*at));
//} //}
return BDD_FALSE; return BDD_FALSE;
} }
BDD SymRS::encNoContext(void) BDD SymRS::encNoContext(void)
{ {
BDD noContextBDD = BDD_TRUE; BDD noContextBDD = BDD_TRUE;
for (unsigned int i = 0; i < totalActions; ++i) for (unsigned int i = 0; i < totalActions; ++i) {
{ noContextBDD *= !(*pv_act)[i];
noContextBDD *= !(*pv_act)[i]; }
}
return noContextBDD; return noContextBDD;
} }
void SymRS::encodeInitStates(void) void SymRS::encodeInitStates(void)
{ {
if (usingContextAutomaton()) if (usingContextAutomaton()) {
{ VERB("Encoding initial states (using context automaton)");
VERB("Encoding initial states (using context automaton)"); encodeInitStatesForCtxAut();
encodeInitStatesForCtxAut(); }
} else {
else VERB("Encoding initial states (for the action entities method -- no CA)");
{ encodeInitStatesNoCtxAut();
VERB("Encoding initial states (for the action entities method -- no CA)"); }
encodeInitStatesNoCtxAut();
} VERB("Initial states encoded");
VERB("Initial states encoded");
} }
void SymRS::encodeInitStatesForCtxAut(void) void SymRS::encodeInitStatesForCtxAut(void)
{ {
initStates = new BDD(BDD_TRUE); initStates = new BDD(BDD_TRUE);
for (unsigned int i = 0; i < totalRctSysStateVars; ++i) for (unsigned int i = 0; i < totalRctSysStateVars; ++i) {
{ *initStates *= !(*pv)[i];
*initStates *= !(*pv)[i]; }
}
*initStates *= getEncCtxAutInitState(); *initStates *= getEncCtxAutInitState();
} }
void SymRS::encodeInitStatesNoCtxAut(void) void SymRS::encodeInitStatesNoCtxAut(void)
{ {
#ifndef NDEBUG #ifndef NDEBUG
if (opts->part_tr_rel)
assert(partTrans != nullptr); if (opts->part_tr_rel) {
assert(partTrans != nullptr);
}
#endif #endif
initStates = new BDD(BDD_FALSE); initStates = new BDD(BDD_FALSE);
for (auto state = rs->initStates.begin(); for (auto state = rs->initStates.begin();
state != rs->initStates.end(); state != rs->initStates.end();
++state) ++state) {
{ VERB("Encoding a single inital state");
VERB("Encoding a single inital state"); BDD newInitState = compState(encEntitiesConj(*state));
BDD newInitState = compState(encEntitiesConj(*state)); BDD q = BDD_TRUE;
BDD q = BDD_TRUE;
if (opts->part_tr_rel)
{
for (unsigned int i = 0; i < partTrans->size(); ++i)
{
q *= newInitState * (*partTrans)[i] * encNoContext();
}
}
else
{
q *= newInitState * *monoTrans * encNoContext();
}
q = (q.ExistAbstract(*pv_E)).SwapVariables(*pv_succ, *pv); if (opts->part_tr_rel) {
q = q.ExistAbstract(*pv_act_E); for (unsigned int i = 0; i < partTrans->size(); ++i) {
q *= newInitState * (*partTrans)[i] * encNoContext();
*initStates += q; }
} }
else {
q *= newInitState * *monoTrans * encNoContext();
}
q = (q.ExistAbstract(*pv_E)).SwapVariables(*pv_succ, *pv);
q = q.ExistAbstract(*pv_act_E);
*initStates += q;
}
} }
void SymRS::mapStateToAct(void) void SymRS::mapStateToAct(void)
{ {
VERB("Mapping state variables to action variables"); VERB("Mapping state variables to action variables");
unsigned int j = 0; unsigned int j = 0;
for (unsigned int i = 0; i < totalRctSysStateVars; ++i)
{ for (unsigned int i = 0; i < totalRctSysStateVars; ++i) {
if (rs->isActionEntity(i)) { if (rs->isActionEntity(i)) {
stateToAct.push_back(j++); stateToAct.push_back(j++);
}
else
{
stateToAct.push_back(-1);
}
} }
const unsigned int verbosity_level = 9; else {
if (opts->verbose > verbosity_level) stateToAct.push_back(-1);
{
for (unsigned int i = 0; i < stateToAct.size(); ++i)
{
cout << "ii VERBOSE(" << verbosity_level << "): stateToAct[" << i << "] = " << stateToAct[i] << endl;
}
} }
}
const unsigned int verbosity_level = 9;
if (opts->verbose > verbosity_level) {
for (unsigned int i = 0; i < stateToAct.size(); ++i) {
cout << "ii VERBOSE(" << verbosity_level << "): stateToAct[" << i << "] = " <<
stateToAct[i] << endl;
}
}
} }
void SymRS::encode(void) void SymRS::encode(void)
{ {
VERB("Encoding..."); VERB("Encoding...");
if (opts->measure) if (opts->measure) {
{ opts->enc_time = cpuTime();
opts->enc_time = cpuTime(); opts->enc_mem = memUsed();
opts->enc_mem = memUsed(); }
}
mapStateToAct(); mapStateToAct();
initBDDvars(); initBDDvars();
if (usingContextAutomaton()) if (usingContextAutomaton()) {
{ encodeCtxAutTrans();
encodeCtxAutTrans(); }
} else {
else VERB_LN(3, "Not using context automata, not encoding TR for CA")
{ }
VERB_LN(3, "Not using context automata, not encoding TR for CA")
}
encodeTransitions(); encodeTransitions();
encodeInitStates(); encodeInitStates();
if (opts->measure) if (opts->measure) {
{ opts->enc_time = cpuTime() - opts->enc_time;
opts->enc_time = cpuTime() - opts->enc_time; opts->enc_mem = memUsed() - opts->enc_mem;
opts->enc_mem = memUsed() - opts->enc_mem; }
}
VERB("Encoding done"); VERB("Encoding done");
} }
BDD SymRS::encActStrEntity(std::string name) const BDD SymRS::encActStrEntity(std::string name) const
{ {
int id = getMappedStateToActID(rs->getEntityID(name)); int id = getMappedStateToActID(rs->getEntityID(name));
if (id < 0)
{ if (id < 0) {
FERROR("Entity \"" << name << "\" not defined as context entity"); FERROR("Entity \"" << name << "\" not defined as context entity");
return BDD_FALSE; return BDD_FALSE;
} else { }
return encActEntity(getMappedStateToActID(rs->getEntityID(name))); else {
} return encActEntity(getMappedStateToActID(rs->getEntityID(name)));
}
} }
size_t SymRS::getCtxAutStateEncodingSize(void) size_t SymRS::getCtxAutStateEncodingSize(void)
{ {
if (!usingContextAutomaton()) return 0; if (!usingContextAutomaton()) {
return 0;
}
assert(rs->ctx_aut != nullptr); assert(rs->ctx_aut != nullptr);
size_t bitCount = 0; size_t bitCount = 0;
size_t bitCountMaxVal = 1; size_t bitCountMaxVal = 1;
size_t numStates = rs->ctx_aut->statesCount(); size_t numStates = rs->ctx_aut->statesCount();
while (bitCountMaxVal <= numStates)
{
bitCount++;
bitCountMaxVal *= 2;
}
VERB_LN(3, "Bits required for CA: " << bitCount); while (bitCountMaxVal <= numStates) {
return bitCount; bitCount++;
bitCountMaxVal *= 2;
}
VERB_LN(3, "Bits required for CA: " << bitCount);
return bitCount;
} }
BDD SymRS::encCtxAutState_raw(State state_id, bool succ) const BDD SymRS::encCtxAutState_raw(State state_id, bool succ) const
{ {
// select appropriate BDD vector // select appropriate BDD vector
vector<BDD> *enc_vec; vector<BDD> *enc_vec;
if (succ)
enc_vec = pv_ca_succ;
else
enc_vec = pv_ca;
assert(enc_vec != nullptr); if (succ) {
enc_vec = pv_ca_succ;
}
else {
enc_vec = pv_ca;
}
BDD r = BDD_TRUE; assert(enc_vec != nullptr);
State val = state_id;
for (unsigned int i = 0; i < totalCtxAutStateVars; ++i) BDD r = BDD_TRUE;
{ State val = state_id;
if (val != 0)
{
if (val % 2 == 1)
{
r *= (*enc_vec)[i];
}
else
{
r *= !(*enc_vec)[i];
}
val /= 2;
}
else
r *= !(*enc_vec)[i];
}
return r; for (unsigned int i = 0; i < totalCtxAutStateVars; ++i) {
if (val != 0) {
if (val % 2 == 1) {
r *= (*enc_vec)[i];
}
else {
r *= !(*enc_vec)[i];
}
val /= 2;
}
else {
r *= !(*enc_vec)[i];
}
}
return r;
} }
BDD SymRS::getEncCtxAutInitState(void) BDD SymRS::getEncCtxAutInitState(void)
{ {
VERB_LN(2, "Encoding context automaton's initial state"); VERB_LN(2, "Encoding context automaton's initial state");
State state = rs->ctx_aut->getInitState(); State state = rs->ctx_aut->getInitState();
return encCtxAutState(state); return encCtxAutState(state);
} }
void SymRS::encodeCtxAutTrans(void) void SymRS::encodeCtxAutTrans(void)
{ {
VERB_LN(2, "Encoding context automaton's transition relation"); VERB_LN(2, "Encoding context automaton's transition relation");
if (tr_ca != nullptr) if (tr_ca != nullptr) {
{ VERB_LN(1, "Encoding for context automaton already present, not replacing")
VERB_LN(1, "Encoding for context automaton already present, not replacing") return;
return; }
}
tr_ca = new BDD(BDD_FALSE); tr_ca = new BDD(BDD_FALSE);
for (auto &t : rs->ctx_aut->transitions) for (auto &t : rs->ctx_aut->transitions) {
{ VERB_LN(2, "Encoding CA transition " << rs->ctx_aut->getStateName(t.src_state)
VERB_LN(2, "Encoding CA transition " << rs->ctx_aut->getStateName(t.src_state) << " -> " << rs->ctx_aut->getStateName(t.dst_state));
<< " -> " << rs->ctx_aut->getStateName(t.dst_state)); BDD enc_src = encCtxAutState(t.src_state);
BDD enc_src = encCtxAutState(t.src_state); BDD enc_dst = encCtxAutStateSucc(t.dst_state);
BDD enc_dst = encCtxAutStateSucc(t.dst_state); BDD enc_ctx = compContext(encActEntitiesConj(t.ctx));
BDD enc_ctx = compContext(encActEntitiesConj(t.ctx));
*tr_ca += enc_src * enc_ctx * enc_dst; *tr_ca += enc_src * enc_ctx * enc_dst;
} }
} }
/** EOF **/ /** EOF **/

191
symrs.hh
View File

@@ -36,7 +36,7 @@ class SymRS
Cudd *cuddMgr; Cudd *cuddMgr;
Options *opts; Options *opts;
// Mapping: entity ID -> action/context entity ID // Mapping: entity ID -> action/context entity ID
StateEntityToAction stateToAct; StateEntityToAction stateToAct;
BDD *initStates; BDD *initStates;
@@ -55,12 +55,12 @@ class SymRS
BDD *monoTrans; BDD *monoTrans;
// Context automaton // Context automaton
vector<BDD> *pv_ca; vector<BDD> *pv_ca;
vector<BDD> *pv_ca_succ; vector<BDD> *pv_ca_succ;
BDD *pv_ca_E; BDD *pv_ca_E;
BDD *pv_ca_succ_E; BDD *pv_ca_succ_E;
BDD *tr_ca; BDD *tr_ca;
vector<BDD> *pv_act; vector<BDD> *pv_act;
BDD *pv_act_E; BDD *pv_act_E;
@@ -69,37 +69,44 @@ class SymRS
unsigned int totalReactions; unsigned int totalReactions;
unsigned int totalRctSysStateVars; unsigned int totalRctSysStateVars;
unsigned int totalActions; unsigned int totalActions;
unsigned int totalCtxAutStateVars; unsigned int totalCtxAutStateVars;
BDD encEntity_raw(Entity entity, bool succ) const; BDD encEntity_raw(Entity entity, bool succ) const;
BDD encEntity(Entity entity) const { BDD encEntity(Entity entity) const
return encEntity_raw(entity, false); {
return encEntity_raw(entity, false);
} }
BDD encActEntity(Entity entity) const { BDD encActEntity(Entity entity) const
assert(entity < pv_act->size()); {
return (*pv_act)[entity]; assert(entity < pv_act->size());
return (*pv_act)[entity];
} }
BDD encEntitySucc(Entity entity) const { BDD encEntitySucc(Entity entity) const
return encEntity_raw(entity, true); {
return encEntity_raw(entity, true);
} }
BDD encEntitiesConj_raw(const Entities &entities, bool succ); BDD encEntitiesConj_raw(const Entities &entities, bool succ);
BDD encEntitiesConj(const Entities &entities) { BDD encEntitiesConj(const Entities &entities)
return encEntitiesConj_raw(entities, false); {
return encEntitiesConj_raw(entities, false);
} }
BDD encEntitiesConjSucc(const Entities &entities) { BDD encEntitiesConjSucc(const Entities &entities)
return encEntitiesConj_raw(entities, true); {
return encEntitiesConj_raw(entities, true);
} }
BDD encEntitiesDisj_raw(const Entities &entities, bool succ); BDD encEntitiesDisj_raw(const Entities &entities, bool succ);
BDD encEntitiesDisj(const Entities &entities) { BDD encEntitiesDisj(const Entities &entities)
return encEntitiesDisj_raw(entities, false); {
return encEntitiesDisj_raw(entities, false);
} }
BDD encEntitiesDisjSucc(const Entities &entities) { BDD encEntitiesDisjSucc(const Entities &entities)
return encEntitiesDisj_raw(entities, true); {
return encEntitiesDisj_raw(entities, true);
} }
BDD encStateActEntitiesConj(const Entities &entities); BDD encStateActEntitiesConj(const Entities &entities);
BDD encStateActEntitiesDisj(const Entities &entities); BDD encStateActEntitiesDisj(const Entities &entities);
BDD encActEntitiesConj(const Entities &entities); BDD encActEntitiesConj(const Entities &entities);
/** /**
* @brief Complements an encoding of a given state by negating all the variables that are not set to true * @brief Complements an encoding of a given state by negating all the variables that are not set to true
@@ -113,122 +120,186 @@ class SymRS
std::string decodedRctSysStateToStr(const BDD &state); std::string decodedRctSysStateToStr(const BDD &state);
void printDecodedRctSysStates(const BDD &states); void printDecodedRctSysStates(const BDD &states);
BDD encNoContext(void); BDD encNoContext(void);
void initBDDvars(void); void initBDDvars(void);
void encodeTransitions(void); void encodeTransitions(void);
void encodeTransitions_old(void); void encodeTransitions_old(void);
void encodeInitStates(void); void encodeInitStates(void);
void encodeInitStatesForCtxAut(void); void encodeInitStatesForCtxAut(void);
void encodeInitStatesNoCtxAut(void); void encodeInitStatesNoCtxAut(void);
void mapStateToAct(void); void mapStateToAct(void);
void encode(void); void encode(void);
int getMappedStateToActID(int stateID) const int getMappedStateToActID(int stateID) const
{ {
assert(stateID < static_cast<int>(totalRctSysStateVars)); assert(stateID < static_cast<int>(totalRctSysStateVars));
return stateToAct[stateID]; return stateToAct[stateID];
} }
size_t getCtxAutStateEncodingSize(void); size_t getCtxAutStateEncodingSize(void);
public: public:
SymRS(RctSys *rs, Options *opts); SymRS(RctSys *rs, Options *opts);
vector<BDD> *getEncPV(void) { return pv; } vector<BDD> *getEncPV(void)
vector<BDD> *getEncPVsucc(void) { return pv_succ; } {
BDD *getEncPV_E(void) { return pv_E; } return pv;
BDD *getEncPVsucc_E(void) { return pv_succ_E; } }
BDD *getEncPVact_E(void) { return pv_act_E; } vector<BDD> *getEncPVsucc(void)
vector<BDD> *getEncPartTrans(void) { return partTrans; } {
BDD *getEncMonoTrans(void) { return monoTrans; } return pv_succ;
}
BDD *getEncPV_E(void)
{
return pv_E;
}
BDD *getEncPVsucc_E(void)
{
return pv_succ_E;
}
BDD *getEncPVact_E(void)
{
return pv_act_E;
}
vector<BDD> *getEncPartTrans(void)
{
return partTrans;
}
BDD *getEncMonoTrans(void)
{
return monoTrans;
}
BDD getEncState(const Entities &entities); BDD getEncState(const Entities &entities);
BDD *getEncInitStates(void) { return initStates; } BDD *getEncInitStates(void)
Cudd *getCuddMgr(void) { return cuddMgr; } {
unsigned int getTotalStateVars(void) { return totalStateVars; } return initStates;
unsigned int getTotalRctSysStateVars(void) { return totalRctSysStateVars; } }
BDD encEntity(std::string name) const { Cudd *getCuddMgr(void)
return encEntity(rs->getEntityID(name)); {
return cuddMgr;
}
unsigned int getTotalStateVars(void)
{
return totalStateVars;
}
unsigned int getTotalRctSysStateVars(void)
{
return totalRctSysStateVars;
}
BDD encEntity(std::string name) const
{
return encEntity(rs->getEntityID(name));
} }
BDD encActStrEntity(std::string name) const; BDD encActStrEntity(std::string name) const;
BDD getBDDtrue(void) const { return BDD_TRUE; } BDD getBDDtrue(void) const
BDD getBDDfalse(void) const { return BDD_FALSE; } {
return BDD_TRUE;
}
BDD getBDDfalse(void) const
{
return BDD_FALSE;
}
/** /**
* @brief Checks if context automaton is used * @brief Checks if context automaton is used
* *
* @return True if CA is used * @return True if CA is used
*/ */
bool usingContextAutomaton(void) { return rs->ctx_aut != nullptr; } bool usingContextAutomaton(void)
{
return rs->ctx_aut != nullptr;
}
/** /**
* @brief Encodes a context automaton's state * @brief Encodes a context automaton's state
* *
* @return Returns the encoded state * @return Returns the encoded state
*/ */
BDD encCtxAutState_raw(State state_id, bool succ) const; BDD encCtxAutState_raw(State state_id, bool succ) const;
/** /**
* @brief Encodes a context automaton's state (as predecessor/non-primed) * @brief Encodes a context automaton's state (as predecessor/non-primed)
* *
* @return Returns the encoded state * @return Returns the encoded state
*/ */
BDD encCtxAutState(State state_id) const { return encCtxAutState_raw(state_id, false); } BDD encCtxAutState(State state_id) const
{
return encCtxAutState_raw(state_id, false);
}
/** /**
* @brief Encodes a context automaton's state (as successor/primed) * @brief Encodes a context automaton's state (as successor/primed)
* *
* @return Returns the encoded state * @return Returns the encoded state
*/ */
BDD encCtxAutStateSucc(State state_id) const { return encCtxAutState_raw(state_id, true); } BDD encCtxAutStateSucc(State state_id) const
{
return encCtxAutState_raw(state_id, true);
}
/** /**
* @brief Encodes the initial state of context automaton * @brief Encodes the initial state of context automaton
* *
* @return Returns the encoded state(s) * @return Returns the encoded state(s)
*/ */
BDD getEncCtxAutInitState(void); BDD getEncCtxAutInitState(void);
/** /**
* @brief Getter for context automaton's state variables (predecessor/non-primed) * @brief Getter for context automaton's state variables (predecessor/non-primed)
* *
* @return Returns a vector of BDDs * @return Returns a vector of BDDs
*/ */
vector<BDD> *getEncCtxAutPV(void) { return pv_ca; } vector<BDD> *getEncCtxAutPV(void)
{
return pv_ca;
}
/** /**
* @brief Getter for context automaton's successor (primed) state variables * @brief Getter for context automaton's successor (primed) state variables
* *
* @return Returns a vector of BDDs * @return Returns a vector of BDDs
*/ */
vector<BDD> *getEncCtxAutPVsucc(void) { return pv_ca_succ; } vector<BDD> *getEncCtxAutPVsucc(void)
{
return pv_ca_succ;
}
/** /**
* @brief Getter for context automaton's quantification BDD (for non-primed vars) * @brief Getter for context automaton's quantification BDD (for non-primed vars)
* *
* @return Returns a BDD for quantification * @return Returns a BDD for quantification
*/ */
BDD *getEncCtxAutPV_E(void) { return pv_ca_E; } BDD *getEncCtxAutPV_E(void)
{
return pv_ca_E;
}
/** /**
* @brief Getter for context automaton's quantification BDD (for primed vars) * @brief Getter for context automaton's quantification BDD (for primed vars)
* *
* @return Returns a BDD for quantification * @return Returns a BDD for quantification
*/ */
BDD *getEncCtxAutPVsucc_E(void) { return pv_ca_succ_E; } BDD *getEncCtxAutPVsucc_E(void)
{
return pv_ca_succ_E;
}
/** /**
* @brief Encodes the monolithic transition relation * @brief Encodes the monolithic transition relation
*/ */
void encodeCtxAutTrans(void); void encodeCtxAutTrans(void);
/** /**
* @brief Getter for context automaton's transition relation * @brief Getter for context automaton's transition relation
* *
* @return Returns a BDD encoding the transition relation * @return Returns a BDD encoding the transition relation
*/ */
BDD *getEncCtxAutTrans(void) { return tr_ca; } BDD *getEncCtxAutTrans(void)
{
return tr_ca;
}
}; };
#endif #endif

View File

@@ -17,9 +17,9 @@
typedef unsigned int Entity; typedef unsigned int Entity;
typedef std::set<Entity> Entities; typedef std::set<Entity> Entities;
struct Reaction { struct Reaction {
Entities rctt; Entities rctt;
Entities inhib; Entities inhib;
Entities prod; Entities prod;
}; };
typedef unsigned int Process; typedef unsigned int Process;
@@ -40,18 +40,18 @@ typedef std::map<std::string, State> StatesByName;
typedef std::map<Process, Entities> EntitiesForProc; typedef std::map<Process, Entities> EntitiesForProc;
struct ReactionCond { struct ReactionCond {
Entities rctt; Entities rctt;
Entities inhib; Entities inhib;
}; };
typedef std::vector<ReactionCond> ReactionConds; typedef std::vector<ReactionCond> ReactionConds;
typedef std::map<Entity,ReactionConds> DecompReactions; typedef std::map<Entity, ReactionConds> DecompReactions;
typedef std::vector<int> StateEntityToAction; typedef std::vector<int> StateEntityToAction;
struct CtxAutTransition { struct CtxAutTransition {
State src_state; State src_state;
Entities ctx; Entities ctx;
State dst_state; State dst_state;
}; };
typedef std::vector<CtxAutTransition> CtxAutTransitions; typedef std::vector<CtxAutTransition> CtxAutTransitions;