/** * Cluster conjuncts to produce a partitioned transition relation. * * Conjuncts larger than limit are rejected (unless they are * singletons). */ vector<BDD> BddTrAttachment::clusterConjunctsOld( vector<BDD>& conjuncts, unsigned int limit, Options::Verbosity verbosity, int nvars) const { vector<BDD> clusters; if (conjuncts.size() == 0) { clusters.push_back(bddManager().bddOne()); return clusters; } vector<BDD>::const_reverse_iterator it = conjuncts.rbegin(); BDD cluster = *it++; conjuncts.pop_back(); while (it != conjuncts.rend()) { reportBDD("conjunct", *it, nvars, verbosity, Options::Informative); BDD tmp = cluster.And(*it,limit); if (tmp && (unsigned int) tmp.nodeCount() <= 2*limit) { cluster = tmp; } else { reportBDD("Cluster", cluster, nvars, verbosity, Options::Informative); clusters.push_back(cluster); cluster = *it; } ++it; conjuncts.pop_back(); } reportBDD("Cluster", cluster, nvars, verbosity, Options::Informative); clusters.push_back(cluster); return clusters; } // BddTrAttachment::clusterConjunctsOld
/** * Quantify local primary input and auxiliary variables. */ BDD BddTrAttachment::quantifyLocalInputs( vector<BDD>& conjuncts, const BDD& qcube, unsigned int limit, Options::Verbosity verbosity) const { // A -1 means "not yet seen." // A -2 means "seen in more than one conjunct." vector<int> whereSeen(bddManager().ReadSize(),-1); for (vector<BDD>::size_type i = 0; i != conjuncts.size(); ++i) { vector<unsigned int> support = conjuncts[i].SupportIndices(); for (vector<unsigned int>::const_iterator j = support.begin(); j != support.end(); ++j) { if (whereSeen[*j] == -1) whereSeen[*j] = i; else whereSeen[*j] = -2; } } // Attempt quantification of variables seen exactly once, but // back off if this blows up the conjunct. vector<unsigned int> qvars = qcube.SupportIndices(); BDD ret = bddManager().bddOne(); for (vector<unsigned int>::size_type i = 0; i != qvars.size(); ++i) { unsigned int index = qvars[i]; BDD bvar = bddManager().bddVar(qvars[i]); int ws = whereSeen[index]; if (ws >= 0) { int currentLimit = conjuncts[ws].nodeCount(); BDD tmp = conjuncts[ws].ExistAbstract(bvar, currentLimit); if (tmp && tmp.nodeCount() <= currentLimit) { conjuncts[ws] = tmp; #if 0 cout << "Eliminated local variable " << index << " from conjunct " << ws << endl; #endif } else { #if 0 cout << "Failed to eliminate local variable " << index << " from conjunct " << ws << endl; #endif ret &= bvar; } } else { ret &= bvar; } } assert(qcube <= ret); if (verbosity > Options::Terse) cout << "Number of clusters/nodes = " << conjuncts.size() << "/" << bddManager().SharingSize(conjuncts) << endl; return ret; } // BddTrAttachment::quantifyLocalInputs
vector<BDD> BddTrAttachment::clusterConjuncts( vector<BDD>& conjuncts, const BDD& qcube, unsigned int limit, Options::Verbosity verbosity) const { vector<BDD> clusters; if (conjuncts.size() == 0) { clusters.push_back(bddManager().bddOne()); return clusters; } // Create records of occurrence of all variables in the conjuncts. // The variables that occur in no conjuncts end up with // earliest > latest. For the others, we know the first and last // conjunct in which they occur. unsigned int numvars = bddManager().ReadSize(); unsigned int nconjuncts = conjuncts.size(); vector<VarRec> occurrence; occurrence.reserve(numvars); for (unsigned int i = 0; i != numvars; ++i) { occurrence.push_back(VarRec(i,nconjuncts,-1)); } for (vector<BDD>::size_type i = 0; i != nconjuncts; ++i) { vector<unsigned int> support = conjuncts[i].SupportIndices(); for (vector<unsigned int>::const_iterator j = support.begin(); j != support.end(); ++j) { if (occurrence[*j].earliest() > (int) i) occurrence[*j].setEarliest((int) i); if (occurrence[*j].latest() < (int) i) occurrence[*j].setLatest((int) i); } } // Filter variables that are not candidates for quantification // and are not present in the conjuncts. vector<unsigned int> qvars = qcube.SupportIndices(); unordered_set<unsigned int> qset(qvars.begin(), qvars.end()); vector<VarRec> candidate; candidate.reserve(qvars.size()); for (vector<VarRec>::const_iterator i = occurrence.begin(); i != occurrence.end(); ++i) { if (qset.find(i->index()) != qset.end() && i->earliest() <= i->latest()) candidate.push_back(*i); } // Sort occurrence records according to latest occurrence // using earliest occurrence as tie breaker. stable_sort(candidate.begin(), candidate.end()); #if 0 // Diagnostic printout. for (vector<VarRec>::const_iterator i = candidate.begin(); i != candidate.end(); ++i) { cout << "Variable: " << i->index() << " (" << i->earliest() << "," << i->latest() << ")\n"; } #endif // We are now ready for clustering having collected the // information of which variables may be quantified when. // In the following, i points to the first conjunct in the cluster. // (Conjunct of highest index since we go backwards.) int i = conjuncts.size() - 1; BDD cluster = conjuncts[i]; conjuncts.pop_back(); // j points to the conjuncts that is being added to the cluster. int j = i - 1; // k points to the candidates for quantification vector<VarRec>::size_type k = 0; while (j >= 0) { reportBDD("conjunct", conjuncts[j], numvars, verbosity, Options::Informative); // Find variables that are local to cluster. A variable is local to // the current cluster if its lifespan is entirely contained between // i and j. BDD qcube = bddManager().bddOne(); while (k < candidate.size() && candidate[k].latest() > (int) i) k++; while (k < candidate.size() && candidate[k].earliest() >= (int) j) { qcube &= bddManager().bddVar(candidate[k].index()); k++; } BDD tmp = cluster.AndAbstract(conjuncts[j], qcube, limit); if (tmp && (unsigned int) tmp.nodeCount() <= 2*limit) { cluster = tmp; } else { reportBDD("Cluster", cluster, numvars, verbosity, Options::Informative); clusters.push_back(cluster); i = j; cluster = conjuncts[i]; } j--; conjuncts.pop_back(); } reportBDD("Cluster", cluster, numvars, verbosity, Options::Informative); clusters.push_back(cluster); return clusters; } // BddTrAttachment::clusterConjuncts