bool Core::check_C2(const ActionSet &le) { for (ActionSet::iterator it = ample.begin(); it != ample.end(); it++) { if (it->type == ActionFire) { if (verif_configuration.is_visible(*it)) { if (cfg_debug) { printf(" C2: %s is visible transition.\n", it->to_string().c_str()); } return false; } } } return true; }
ActionSet Core::compute_ample_set(State *s, const ActionSet &enable) { ActionSet::iterator it; if (cfg_debug) { // print state name char *hashstr = (char*) alloca(mhash_get_block_size(MHASH_MD5) * 2 + 1); hashdigest_to_string(MHASH_MD5, s->compute_hash(MHASH_MD5) , hashstr); printf(">> state: %s: \nenable: { ", hashstr); for (it = enable.begin(); it != enable.end(); it++) { printf("%s ", it->to_string().c_str()); } printf("}\n"); } for (it = enable.begin(); it != enable.end(); it++) { ActionSet ample; ample.insert(*it); if (cfg_debug) { printf(" > ample: { "); for (ActionSet::iterator i = ample.begin(); i != ample.end(); i++) { printf("%s ", i->to_string().c_str()); } printf("}\n"); } if (check_C1(enable, ample, s) && check_C2(ample) && check_C3(s)) { if (cfg_debug) { printf(" This ample set is independent.\n"); } return ample; } if (cfg_wait_for_key) { getchar(); } } return enable; }
bool Core::check_C1(const ActionSet &enabled, const ActionSet &le, State *s) { ActionSet::iterator it1; ActionSet::iterator it2; std::deque<Action> queue; // This assume that there is no optimization for number of tokens in places ActionSet processed = ample; std::vector<bool> receive_blocked(ca::process_count * ca::process_count, false); std::vector<int> enabled_priorities(ca::process_count, 0); std::vector<int> marking = verif_configuration.get_marking(s); if (cfg_debug) { printf(" C1: Marking: {"); int place_count = marking.size() / ca::process_count; for (size_t i = 0; i < marking.size(); i++) { printf(" %d", marking[i]); if ((i + 1) % place_count == 0 && i + 1 != marking.size()) { printf(" |"); } } printf(" }\n"); printf(" C1: starting configuration {"); } for (ActionSet::iterator i = enabled.begin(); i != enabled.end(); i++) { if (ample.find(*i) != ample.end()) { if (i->type == ActionReceive) { receive_blocked[i->process * ca::process_count + i->data.receive.source] = true; } if (i->type == ActionFire) { enabled_priorities[i->process] = i->data.fire.transition_def->get_priority(); } } else { if (i->type == ActionFire) { processed.insert(*i); queue.push_back(*i); if (cfg_debug) { printf(" %s", i->to_string().c_str()); } const std::vector<ca::TransitionDef*> &transitions = net_def->get_transition_defs(); for (int t = 0; t < net_def->get_transitions_count(); t++) { if (transitions[t]->get_priority() >= enabled_priorities[i->process]) continue; if (s->is_transition_enabled(i->process, transitions[t])) { Action a; a.type = ActionFire; a.data.fire.transition_def = transitions[t]; a.process = i->process; processed.insert(a); queue.push_back(a); if (cfg_debug) { printf(" %s", a.to_string().c_str()); } } } continue; } if (i->type == ActionReceive) { const State::PacketQueue& pq = s->get_packets(i->process, i->data.receive.source); for (size_t p = 0; p < pq.size(); p++) { Action a; a.type = ActionReceive; a.process = i->process; a.data.receive.source = i->data.receive.source; ca::Tokens *tokens = (ca::Tokens *) pq[p].data; a.data.receive.edge_id = tokens->edge_id; if (processed.find(a) == processed.end()) { processed.insert(a); queue.push_back(a); if (cfg_debug) { printf(" %s", a.to_string().c_str()); } } } continue; } processed.insert(*i); queue.push_back(*i); if (cfg_debug) { printf(" %s", i->to_string().c_str()); } } } if (cfg_debug) { printf(" }\n"); } while(queue.size() > 0) { for (ActionSet::iterator a = ample.begin(); a != ample.end(); a++) { if (verif_configuration.is_dependent(*a, queue.front(), marking)) { if (cfg_debug) { printf(" C1: %s and %s are dependent.\n", a->to_string().c_str(), queue.front().to_string().c_str()); } return false; } } if (cfg_debug) { size_t i = queue.size(); verif_configuration.compute_successors(queue.front(), queue, processed, receive_blocked, enabled_priorities, marking); printf(" C1: successors of %s: {", queue.front().to_string().c_str()); for (; i < queue.size(); i++) { printf(" %s", queue[i].to_string().c_str()); } printf(" }\n"); } else { verif_configuration.compute_successors(queue.front(), queue, processed, receive_blocked, enabled_priorities, marking); } queue.pop_front(); } return true; }
void Node::generate(Core *core) { if (state->get_quit_flag()) { return; } ActionSet enabled = compute_enable_set(core); ActionSet ws; if (cfg_partial_order_reduction) { ws = core->compute_ample_set(state, enabled); } else { ws = enabled; } State *s; ActionSet::iterator it; for (it = ws.begin(); it != ws.end(); it++) { if (++it != ws.end()) { s = new State(*state); } else { s = state; } it--; switch (it->type) { case ActionFire: { ca::Packer packer; if (core->generate_binding_in_nni(it->data.fire.transition_def->get_id())) { s->fire_transition_full_with_binding(it->process, it->data.fire.transition_def, packer); } else { s->fire_transition_full(it->process, it->data.fire.transition_def); } Node *n = core->add_state(s, this); NextNodeInfo nninfo; nninfo.node = n; nninfo.action = ActionFire; nninfo.data.fire.process_id = it->process; nninfo.data.fire.transition_id = it->data.fire.transition_def->get_id(); if (core->generate_binding_in_nni(it->data.fire.transition_def->get_id())) { nninfo.data.fire.binding = core->hash_packer(packer); } else { nninfo.data.fire.binding = NULL; } nexts.push_back(nninfo); packer.free(); break; } case ActionReceive: { s->receive(it->process, it->data.receive.source, true); Node *n = core->add_state(s, this); NextNodeInfo nninfo; nninfo.node = n; nninfo.action = ActionReceive; nninfo.data.receive.process_id = it->process; nninfo.data.receive.source_id = it->data.receive.source; nexts.push_back(nninfo); break; } } } }