/**
 * Compute the preimage of a set of states.
 */
BDD BddTrAttachment::preimg(const BDD& from) const
{
  BDD preimgx = from.SwapVariables(_yvars,_xvars);
  preimgx = preimgx.ExistAbstract(_prequanty);
  for (vector< RelPart >::const_iterator it = _tr.begin();
       it != _tr.end(); ++it) {
    preimgx = preimgx.AndAbstract(it->part(), it->bwQuantCube());
  }
  return preimgx;

} // BddTrAttachment::preimg
/**
 * Compute the image of a set of states.
 */
BDD BddTrAttachment::img(const BDD& from) const
{
  BDD imgy = from.ExistAbstract(_prequantx);
  for (vector< RelPart >::const_iterator it = _tr.begin();
       it != _tr.end(); ++it) {
    imgy = imgy.AndAbstract(it->part(), it->fwQuantCube());
  }
  BDD imgx = imgy.SwapVariables(_xvars,_yvars);
  return imgx;

} // BddTrAttachment::img
/**
 * Eliminate auxiliary variables from output function.
 */
BDD BddTrAttachment::flattenOutput(
  const vector<BDD>& conjuncts,
  const BDD& wCube)
{
  vector<BDD> schedule;
  for (vector<BDD>::size_type i = 0; i != conjuncts.size(); ++i) {
    schedule.push_back(bddManager().bddOne());
  }

  // For each variable appearing in the conjuncts find the last
  // conjunct in which it appears.
  vector<int> lastSeen(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) {
      lastSeen[*j] = i;
    }
  }

  vector<unsigned int> wVars = wCube.SupportIndices();
#if 0
  printVector("wVars", wVars); // Diagnostic printout.
#endif
  for (vector<unsigned int>::size_type i = 0; i != wVars.size(); ++i) {
    unsigned int index = wVars[i];
    int ls = lastSeen[index];
    if (ls >= 0) {
      BDD var = bddManager().bddVar(index);
      schedule[ls] &= var;
    }
  }

  BDD ret = bddManager().bddOne();
  for (vector<BDD>::size_type i = 0; i != conjuncts.size(); ++i) {
    ret = ret.AndAbstract(conjuncts[i], schedule[i]);
  }
  return ret;

} // BddTrAttachment::flattenOutput
/**
 * Compose auxiliary functions recursively into a BDD.
 */
void BddTrAttachment::composeAuxiliaryFunctions(
  BddAttachment const * bat,
  BDD & f,
  unordered_map<int, ID> const & index2id)
{
  vector<unsigned int> support = f.SupportIndices();
  queue< vector<unsigned int> > q;
  q.push(support);
  while (!q.empty()) {
    vector<unsigned int> supp = q.front();
    q.pop();
    for (vector<unsigned int>::const_iterator j = supp.begin();
         j != supp.end(); ++j) {
      unordered_map<int,ID>::const_iterator cit = index2id.find(*j);
      if (cit != index2id.end()) {
        BDD g = bat->bdd(cit->second);
        BDD a = bddManager().bddVar(*j);
        f = f.AndAbstract(a.Xnor(g),a);
        vector<unsigned int> addSupp = g.SupportIndices();
        q.push(addSupp);
      }
    }
  }
}
Beispiel #5
0
BDD Synth::pre_sys(BDD dst) {
    /**
    Calculate predecessor states of given states.

        ∀u ∃c ∃t': tau(t,u,c,t') & dst(t') & ~error(t,u,c)

    We use the direct substitution optimization (since t' <-> BDD(t,u,c)), thus:

        ∀u ∃c: (!error(t,u,c)  &  (dst(t)[t <- bdd_next_t(t,u,c)]))

    or for Moore machines:

        ∃c ∀u: (!error(t,u,c)  &  (dst(t)[t <- bdd_next_t(t,u,c)]))

    Note that we do not replace t variables in the error bdd.

    :return: BDD of the predecessor states
    **/

    // NOTE: I tried considering two special cases: error(t,u,c) and error(t),
    //       and move error(t) outside of quantification ∀u ∃c.
    //       It slowed down..
    // TODO: try again: on the driver example

    static vector<VecUint> orders;
    static bool did_grouping = false;

    if (!did_grouping && timer.sec_from_origin() > time_limit_sec/4) { // at 0.25*time_limit we fix the order
        do_grouping(cudd, orders);
        did_grouping = true;
    }

    dst = dst.VectorCompose(get_substitution());                                update_order_if(cudd, orders);

    if (is_moore) {
        BDD result = dst.And(~error);

        vector<BDD> uncontrollable = get_uncontrollable_vars_bdds();
        if (!uncontrollable.empty()) {
            BDD uncontrollable_cube = cudd.bddComputeCube(uncontrollable.data(),
                                                          NULL,
                                                          (int)uncontrollable.size());
            result = result.UnivAbstract(uncontrollable_cube);                  update_order_if(cudd, orders);
        }

        // ∃c ∀u  (...)
        vector<BDD> controllable = get_controllable_vars_bdds();
        BDD controllable_cube = cudd.bddComputeCube(controllable.data(),
                                                    NULL,
                                                    (int)controllable.size());
        result = result.ExistAbstract(controllable_cube);                       update_order_if(cudd, orders);
        return result;
    }

    // the case of Mealy machines
    vector<BDD> controllable = get_controllable_vars_bdds();
    BDD controllable_cube = cudd.bddComputeCube(controllable.data(),
                                                NULL,
                                                (int)controllable.size());
    BDD result = dst.AndAbstract(~error, controllable_cube);                   update_order_if(cudd, orders);

    vector<BDD> uncontrollable = get_uncontrollable_vars_bdds();
    if (!uncontrollable.empty()) {
        // ∀u ∃c (...)
        BDD uncontrollable_cube = cudd.bddComputeCube(uncontrollable.data(),
                                                      NULL,
                                                      (int)uncontrollable.size());
        result = result.UnivAbstract(uncontrollable_cube);                    update_order_if(cudd, orders);
    }
    return result;
}
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