Example #1
0
/**
 * 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
Example #2
0
/**
 * 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
Example #3
0
/**
 * 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
Example #4
0
/**
 * 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
Example #5
0
File: Synth.cpp Project: 5nizza/sdf
void Synth::model_to_aiger(const BDD &c_signal, const BDD &func) {
    /// Update AIGER spec with a definition of `c_signal`

    uint c_lit = aiger_by_cudd[c_signal.NodeReadIndex()];
    string output_name = string(aiger_is_input(aiger_spec, c_lit)->name);  // save the name before it is freed

    uint func_as_aiger_lit = walk(func.getNode());

    aiger_redefine_input_as_and(aiger_spec, c_lit, func_as_aiger_lit, func_as_aiger_lit);

    if (print_full_model)
        aiger_add_output(aiger_spec, c_lit, output_name.c_str());
}
Example #6
0
void Jeu::conjugaison()    /// boucle principale du jeu
{
    srand(SDL_GetTicks());
    m_in->activerSaisie();

    BDD * dico = new BDD("ressources/datas/database.db");

    for(int i = 0 ; i < 20 ; i++)
    {
        std::vector<std::vector<std::string> > dataC;
        int hazard = rand()%(10-1) + 1;
        string temp = "SELECT nom,pluralite,personne FROM pronom WHERE id = " + toString(hazard);
        dataC = dico->request((char*)temp.c_str());
        data2[i*5+0] = dataC[0][0];
        data2[i*5+2] = dataC[0][1];
        data2[i*5+3] = dataC[0][2];
        hazard = rand()%(4-1) + 1;
        temp = "SELECT infinitif FROM verbe WHERE id = " + toString(hazard);
        dataC = dico->request((char*)temp.c_str());
        data2[i*5+4] = dataC[0][0];
        temp = "SELECT " + data2[i*5+3] + "_" + data2[i*5+2] + " FROM indicatif_present WHERE id = " + toString(hazard);
        dataC = dico->request((char*)temp.c_str());
        data2[i*5+1] = dataC[0][0];

        cout << data2[i*5+0] << " " << data2[i*5+1] << " " << data2[i*5+2] << " " << data2[i*5+3] << " " << data2[i*5+4] << endl;
    }

    delete dico;

    while(!m_in->get_touche(SDLK_ESCAPE) && !m_in->get_exit())
    {
        /// met à jour les evenements d'entree
        m_in->update();
        /// régule le fps
        timer();
        /// resize taille écran
        resizeScreen();

        /// mécanique du jeu
        mecanique2();
        /// affichage du jeu
        affichage2();
    }
}
Example #7
0
/**
 * 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
Example #8
0
/**
  Reads a file containing a binary relation. One pair per line.
 */
BDD read_binrel(const char* fname) {
  unordered_map<int,int> normalize;

  BDD br = Cudd::zero();

  string line;
  ifstream input(fname);
  if (input.is_open()) {
    while (input.good()) {
      getline(input,line);
      stringstream ss(line);
      int first, second;
      ss >> first; ss >> second;

      encode(normalize,first);
      encode(normalize, second);
      br |= BDD::create(make_tuple(first,second));
      //tuples.push_back(make_pair(first,second));
    }
    input.close();
    cout << "Pairs in the relation: " << br.minterms(2) << endl;
    //Cudd::stats();
  } else {
Example #9
0
/**
 * 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);
      }
    }
  }
}
Example #10
0
int execQueens(int n, std::string com)
{
  // clocks for performance analysis
  clock_t start, end;
	double elapsed;
  start = clock();

  std::ostringstream namefich;
  BDD* bdd = new BDD();
  bdd->setNbVar(n*n);
  int pos = 0;
  std::ostringstream oss;
  namefich << "test" << pos << ".txt";
  std::string namefichstr = namefich.str();
  std::ofstream fichier(namefichstr, std::ios::out | std::ios::trunc);
  namefich.str("");
  namefich.clear();
  BDD* bdd1 = new BDD(bdd->getNbVar(), bdd->getVectorNode(), bdd->getVectNode(), bdd->getNodeFalse(), bdd->getNodeTrue(), bdd->getVarorder(), bdd->getOrdervar(), bdd->getMaxIndice(), bdd->getOpmap());
  BDD* bddtemp1;
  for (int i=0; i < n; i++)
  {
    bddtemp1 = new BDD(bdd1->getNbVar(), bdd1->getVectorNode(), bdd1->getVectNode(), bdd1->getNodeFalse(), bdd1->getNodeTrue(), bdd1->getVarorder(), bdd1->getOrdervar(), bdd1->getMaxIndice(), bdd1->getOpmap());
    for (int j=0; j < n; j++)
    {
      oss << "( c"<<i<<j<<" & ";
      bool first = true;
      for (int h = 0; h < n; h++)
      {
        if (h != j)
        {
          if (!first)
            oss << " & ";
          oss << "!c"<<i<<h;
          first = false;
        }
      }
      oss << " )";
      bddtemp1 = bddtemp1->orfonc(bddtemp1, oss.str());
      oss.str("");
      oss.clear();
    }
    bdd1 = bdd1->andfonc(bdd1, bddtemp1);
    bdd1 = bdd1->transferinfo(bddtemp1, bdd1);
    oss.str("");
    oss.clear();
  }
  std::cout << "fin premier bdd" << std::endl;
  /*oss << " & ";*/
  BDD* bdd2 = new BDD(bdd1->getNbVar(), bdd1->getVectorNode(), bdd1->getVectNode(), bdd1->getNodeFalse(), bdd1->getNodeTrue(), bdd1->getVarorder(), bdd1->getOrdervar(), bdd1->getMaxIndice(), bdd1->getOpmap());
  BDD* bddtemp2;
  for (int i=0; i < n; i++)
  {
    bddtemp2 = new BDD(bdd2->getNbVar(), bdd2->getVectorNode(), bdd2->getVectNode(), bdd2->getNodeFalse(), bdd2->getNodeTrue(), bdd2->getVarorder(), bdd2->getOrdervar(), bdd2->getMaxIndice(), bdd2->getOpmap());
    for (int j=0; j < n; j++)
    {
      oss << "( c"<<j<<i<<" & ";
      bool first = true;
      for (int h = 0; h < n; h++)
      {
        if (h != j)
        {
          if (!first)
            oss << " & ";
          oss << "!c"<<h<<i;
          first = false;
        }
      }
      oss << " )";
      bddtemp2 = bddtemp2->orfonc(bddtemp2, oss.str());
      oss.str("");
      oss.clear();
    }
    bdd2 = bdd2->andfonc(bdd2, bddtemp2);
    bdd2 = bdd2->transferinfo(bddtemp2, bdd2);
    oss.str("");
    oss.clear();
  }
  std::cout << "fin second bdd" << std::endl;
  /*oss << " & ";*/
  BDD* bdd3 = new BDD(bdd2->getNbVar(), bdd2->getVectorNode(), bdd2->getVectNode(), bdd2->getNodeFalse(), bdd2->getNodeTrue(), bdd2->getVarorder(), bdd2->getOrdervar(), bdd2->getMaxIndice(), bdd2->getOpmap());
  BDD* bddtemp3;
  for (int i = 0; i < n; i++)
  {
    bddtemp3 = new BDD(bdd3->getNbVar(), bdd3->getVectorNode(), bdd3->getVectNode(), bdd3->getNodeFalse(), bdd3->getNodeTrue(), bdd3->getVarorder(), bdd3->getOrdervar(), bdd3->getMaxIndice(), bdd3->getOpmap());
    for (int j=0; j < n; j++)
    {
      oss << "( c"<<i<<j;
      std::ostringstream osstemp;
      bool first = true;
      for (int h = 0; h < n; h++)
      {
        int val = j+h-i;
        if (h != i && val>=0 && val<n)
        {
          if (first)
            osstemp <<" & ( ";
          if (!first)
            osstemp << " & ";
          osstemp << "!c"<<h<<val;
          first = false;
        }
      }
      std::string temp = osstemp.str();
      if (temp != "")
        oss << temp << " ) )";
      else
        oss << " )";
      bddtemp3 = bddtemp3->orfonc(bddtemp3, oss.str());
      oss.str("");
      oss.clear();
    }
    bdd3 = bdd3->andfonc(bdd3, bddtemp3);
    bdd3 = bdd3->transferinfo(bddtemp3, bdd3);
    oss.str("");
    oss.clear();
  }
  std::cout << "fin troisieme bdd" << std::endl;
  /*oss << " & ";*/
  BDD* bdd4 = new BDD(bdd3->getNbVar(), bdd3->getVectorNode(), bdd3->getVectNode(), bdd3->getNodeFalse(), bdd3->getNodeTrue(), bdd3->getVarorder(), bdd3->getOrdervar(), bdd3->getMaxIndice(), bdd3->getOpmap());
  BDD* bddtemp4;
  for (int i = 0; i < n; i++)
  {
    bddtemp4 = new BDD(bdd4->getNbVar(), bdd4->getVectorNode(), bdd4->getVectNode(), bdd4->getNodeFalse(), bdd4->getNodeTrue(), bdd4->getVarorder(), bdd4->getOrdervar(), bdd4->getMaxIndice(), bdd4->getOpmap());
    for (int j=0; j < n; j++)
    {
      oss << "( c"<<i<<j;
      std::ostringstream osstemp;
      bool first = true;
      for (int h = 0; h < n; h++)
      {
        int val = j+i-h;
        if (h != i && val>=0 && val<n)
        {
          if (first)
            osstemp <<" & ( ";
          if (!first)
            osstemp << " & ";
          osstemp << "!c"<<h<<val;
          first = false;
        }
      }
      std::string temp = osstemp.str();
      if (temp != "")
        oss << temp << " ) )";
      else
        oss << " )";
      bddtemp4 = bddtemp4->orfonc(bddtemp4, oss.str());
      oss.str("");
      oss.clear();
    }
    bdd4 = bdd4->andfonc(bdd4, bddtemp4);
    bdd4 = bdd4->transferinfo(bddtemp4, bdd4);
    oss.str("");
    oss.clear();
  }
  std::cout << "fin quatrieme bdd" << std::endl;
  bdd = bdd->andfonc(bdd, bdd1);
  std::cout << "fin apply1" << std::endl;
  bdd = bdd->andfonc(bdd, bdd2);
  std::cout << "fin apply2" << std::endl;
  bdd = bdd->andfonc(bdd, bdd3);
  std::cout << "fin apply3" << std::endl;
  bdd = bdd->andfonc(bdd, bdd4);
  std::cout << "fin apply4" << std::endl;
  if (com == "satcount")
    std::cout << "Nombre de solution satisfaisante pour bdd: " << bdd->satcount() << std::endl;
  else if (com == "anysat")
    std::cout << "Une solution: " << bdd->anysat() << std::endl;
  else if (com == "allsat")
  {
	std::cout << "Toutes les solutions:" << std::endl;
    bdd->allsat();
  }



  // performance analysis
  end = clock();
  elapsed = ((double)end - start) / CLOCKS_PER_SEC;
  std::cout << "Execution time : " << elapsed << std::endl;

  return 0;
}
Example #11
0
File: Synth.cpp Project: 5nizza/sdf
hmap<uint,BDD> Synth::extract_output_funcs() {
    /** The result vector respects the order of the controllable variables **/

    L_INF("extract_output_funcs..");

    cudd.FreeTree();    // ordering that worked for win region computation might not work here

    hmap<uint,BDD> model_by_cuddidx;

    vector<BDD> controls = get_controllable_vars_bdds();

    while (!controls.empty()) {
        BDD c = controls.back(); controls.pop_back();

        aiger_symbol *aiger_input = aiger_is_input(aiger_spec, aiger_by_cudd[c.NodeReadIndex()]);
        L_INF("getting output function for " << aiger_input->name);

        BDD c_arena;
        if (controls.size() > 0) {
            BDD cube = cudd.bddComputeCube(controls.data(), NULL, (int)controls.size());
            c_arena = non_det_strategy.ExistAbstract(cube);
        }
        else { //no other signals left
            c_arena = non_det_strategy;
        }
        // Now we have: c_arena(t,u,c) = ∃c_others: nondet(t,u,c)
        // (i.e., c_arena talks about this particular c, about t and u)

        BDD c_can_be_true = c_arena.Cofactor(c);
        BDD c_can_be_false = c_arena.Cofactor(~c);

        BDD c_must_be_true = ~c_can_be_false & c_can_be_true;
        BDD c_must_be_false = c_can_be_false & ~c_can_be_true;
        // Note that we cannot use `c_must_be_true = ~c_can_be_false`,
        // since the negation can cause including tuples (t,i,o) that violate non_det_strategy.

        auto support_indices = cudd.SupportIndices(vector<BDD>({c_must_be_false, c_must_be_true}));
        for (auto const var_cudd_idx : support_indices) {
            auto v = cudd.ReadVars(var_cudd_idx);
            auto new_c_must_be_false = c_must_be_false.ExistAbstract(v);
            auto new_c_must_be_true = c_must_be_true.ExistAbstract(v);

            if ((new_c_must_be_false & new_c_must_be_true) == cudd.bddZero()) {
                c_must_be_false = new_c_must_be_false;
                c_must_be_true = new_c_must_be_true;
            }
        }

        // We use 'restrict' operation, but we could also just do:
        //     c_model = care_set -> must_be_true
        // but this is (presumably) less efficient (in time? in size?).
        // (intuitively, because we always set c_model to 1 if !care_set, but we could set it to 0)
        //
        // The result of restrict operation satisfies:
        //     on c_care_set: c_must_be_true <-> must_be_true.Restrict(c_care_set)

        BDD c_model = c_must_be_true.Restrict(c_must_be_true | c_must_be_false);

        model_by_cuddidx[c.NodeReadIndex()] = c_model;

        //killing node refs
        c_must_be_false = c_must_be_true = c_can_be_false = c_can_be_true = c_arena = cudd.bddZero();

        //TODO: ak: strange -- the python version for the example amba_02_9n produces a smaller circuit (~5-10 times)!
        non_det_strategy = non_det_strategy.Compose(c_model, c.NodeReadIndex());
        //non_det_strategy = non_det_strategy & ((c & c_model) | (~c & ~c_model));
    }

    return model_by_cuddidx;
}
Example #12
0
File: Synth.cpp Project: 5nizza/sdf
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;
}
Example #13
0
/**
 * Compute the quantification schedule for the primary inputs and the
 * auxiliary variables.
 */
void BddTrAttachment::computeSchedule(
  const vector<BDD>& conjuncts,
  const BDD& wCube)
{
  vector<BDD> fwSchedule, bwSchedule;
  for (vector<BDD>::size_type i = 0; i != conjuncts.size(); ++i) {
    fwSchedule.push_back(bddManager().bddOne());
    bwSchedule.push_back(bddManager().bddOne());
  }
  _prequantx = bddManager().bddOne();
  _prequanty = 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);
      fwSchedule[ls] &= var;
      bwSchedule[ls] &= var;
    }
  }

  for (vector<BDD>::size_type i = 0; i != _xvars.size(); ++i) {
    unsigned int index = _xvars[i].NodeReadIndex();
    int ls = lastSeen[index];
    if (ls >= 0) {
      fwSchedule[ls] &= _xvars[i];
    } else {
      _prequantx &= _xvars[i];
    }
  }

  for (vector<BDD>::size_type i = 0; i != _yvars.size(); ++i) {
    unsigned int index = _yvars[i].NodeReadIndex();
    int ls = lastSeen[index];
    if (ls >= 0) {
      bwSchedule[ls] &= _yvars[i];
    } else {
      _prequanty &= _yvars[i];
    }
  }

  for (vector<BDD>::size_type i = 0; i != conjuncts.size(); ++i) {
    _tr.push_back(RelPart(conjuncts[i], fwSchedule[i], bwSchedule[i]));
  }

} // BddTrAttachment::computeSchedule
Example #14
0
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
Example #15
0
/**
 * Build BDDs for the transition relation of the model.
 */
void BddTrAttachment::build()
{
  Options::Verbosity verbosity = _model.verbosity();
  if (verbosity > Options::Silent)
    cout << "Computing transition relation for model " << _model.name() << endl;
  BddAttachment const * bat = 
    (BddAttachment const *) _model.constAttachment(Key::BDD);
  assert(bat != 0);
  // The BDD attachment may not have BDDs because of a timeout.
  if (bat->hasBdds() == false) {
    _model.constRelease(bat);
    return;
  }
  if (hasBdds())
    return;
  ExprAttachment const * eat =
    (ExprAttachment *) _model.constAttachment(Key::EXPR);
  Expr::Manager::View *v = _model.newView();
  resetBddManager("bdd_tr_timeout");

  try {
    // Gather the conjuncts of the transition relation and initial condition.
    const vector<ID> sv = eat->stateVars();
    const vector<ID> iv = eat->inputs();
    const unordered_map<ID, int>& auxVar = bat->auxiliaryVars();
    int nvars = 2 * sv.size() + iv.size() + auxVar.size();
    if (verbosity > Options::Terse)
      cout << "number of variables = " << nvars << endl;
    BDD inputCube = bddManager().bddOne();
    for (vector<ID>::const_iterator i = iv.begin(); i != iv.end(); ++i) {
      BDD w = bat->bdd(*i);
      inputCube &= w;
    }
    BDD fwAbsCube = bddManager().bddOne();
    BDD bwAbsCube = bddManager().bddOne();
    vector<BDD> conjuncts;
    for (vector<ID>::const_iterator i = sv.begin(); i != sv.end(); ++i) {
      BDD x = bat->bdd(*i);
      _xvars.push_back(x);
      fwAbsCube &= x;
      ID nsv = v->prime(*i);
      BDD y = bat->bdd(nsv);
      _yvars.push_back(y);
      bwAbsCube &= y;
      ID nsf = eat->nextStateFnOf(*i);
      BDD f = bat->bdd(nsf);
      if (verbosity > Options::Informative)
        if (f.IsVar())
          cout << "Found a variable next-state function" << endl; 
      BDD t = y.Xnor(f);
      if (verbosity > Options::Verbose)
        reportBDD(stringOf(*v, nsv) + " <-> " + stringOf(*v, nsf),
                  t, nvars, verbosity, Options::Verbose);
      conjuncts.push_back(t);
    }

    // Process auxiliary variables.
    vector<BDD> conjAux;
    for (unordered_map<ID, int>::const_iterator it = auxVar.begin();
         it != auxVar.end(); ++it) {
      BDD f = bat->bdd(it->first);
      BDD v = bddManager().bddVar(it->second);
      BDD t = v.Xnor(f);
      conjAux.push_back(t);
      inputCube &= v;
    }
    conjuncts.insert(conjuncts.end(), conjAux.begin(), conjAux.end());
    // Build map from BDD variable indices to expression IDs.
    unordered_map<int, ID> index2id;
    for (unordered_map<ID, int>::const_iterator it = auxVar.begin();
         it != auxVar.end(); ++it) {
      index2id[it->second] = it->first;
    }

    // Add invariant constraints.
    const vector<ID> constr = eat->constraintFns();
    for (vector<ID>::const_iterator i = constr.begin(); 
         i != constr.end(); ++i) {
      BDD cn = bat->bdd(*i);
      composeAuxiliaryFunctions(bat, cn, index2id);
      _constr.push_back(cn);
      BDD cny = cn.ExistAbstract(inputCube);
      cny = cny.SwapVariables(_yvars, _xvars);
      reportBDD("Invariant constraint", cn, nvars, verbosity, Options::Terse);
      conjuncts.push_back(cn);
      conjuncts.push_back(cny);
    }

    unsigned int clusterLimit = 2500;
    if (_model.options().count("bdd_tr_cluster")) {
      clusterLimit = _model.options()["bdd_tr_cluster"].as<unsigned int>();
    }

    // Collect output functions applying invariant constraints and substituting
    // auxiliary variables.
    const vector<ID> outf = eat->outputs();
    for (vector<ID>::const_iterator i = outf.begin(); i != outf.end(); ++i) {
      BDD of = bat->bdd(eat->outputFnOf(*i));
      // Apply invariant constraints.
      for (vector<BDD>::iterator i = _constr.begin(); i != _constr.end(); ++i)
        of &= *i;
      composeAuxiliaryFunctions(bat, of, index2id);
      // Finally, remove primary inputs.
      if (_model.defaultMode() != Model::mFAIR) {
        of = of.ExistAbstract(inputCube);
      }
      _inv.push_back(of);
      reportBDD("Output function", of, _xvars.size(), verbosity,
                Options::Terse);
    }

    // Build the transition relation from the conjuncts.
    vector<BDD> sortedConjuncts = linearArrangement(conjuncts);
    assert(sortedConjuncts.size() == conjuncts.size());
    conjuncts.clear();
    vector<BDD> clusteredConjuncts =
      clusterConjuncts(sortedConjuncts, inputCube, clusterLimit, verbosity);
    assert(sortedConjuncts.size() == 0);
    inputCube = quantifyLocalInputs(clusteredConjuncts, inputCube,
                                    clusterLimit, verbosity);
    computeSchedule(clusteredConjuncts, inputCube);

    // Build initial condition.
    const vector<ID> ini = eat->initialConditions();
    _init = bddManager().bddOne();
    for (vector<ID>::const_iterator i = ini.begin(); i != ini.end(); ++i) {
      BDD ic = bat->bdd(*i);
      _init &= ic;
    }
    reportBDD("Initial condition", _init, _xvars.size(), verbosity,
              Options::Terse);
  } catch (Timeout& e) {
    bddManager().ClearErrorCode();
    bddManager().UnsetTimeLimit();
    bddManager().ResetStartTime();
    if (verbosity > Options::Silent)
      std::cout << e.what() << std::endl;
    _tr.clear();
    _xvars.clear();
    _yvars.clear();
    _inv.clear();
    _prequantx = bddManager().bddOne();
    _prequanty = bddManager().bddOne();
    _init = bddManager().bddZero();
  }
  delete v;
  _model.constRelease(eat);
  _model.constRelease(bat);

  bddManager().UpdateTimeLimit();

} // BddTrAttachment::build
unsigned approximate_additional_lines( const std::string& filename, properties::ptr settings, properties::ptr statistics )
{
  /* Timer */
  properties_timer t( statistics );

  /* Number of inputs and outputs */
  unsigned n = 0u;
  unsigned m = 0u;

  /* Parse PLA */
  std::ifstream is;
  is.open(filename.c_str());

  std::string line;

  /* For the BDD */
  Cudd mgr(0, 0);
  BDD u = mgr.bddZero();
  std::vector<BDD> variables;

  /* MU hash table */
  std::map<std::string, mpz_class> mu;

  while(std::getline(is, line)) {
    using boost::algorithm::starts_with;
    using boost::algorithm::trim;

    trim(line);
    if (line.size() == 0u) continue;

    if (starts_with(line, ".i ")) {
      n = parse_number_from_pla_command(line);
      variables.resize(n);
      boost::generate(variables, [&mgr](){ return mgr.bddVar(); });
    } else if (starts_with(line, ".o ")) {
      m = parse_number_from_pla_command(line);
    } else if (starts_with(line, "#")) {
      /* ignore comments */
    } else if (!starts_with(line, ".")) {
      using boost::algorithm::split;
      using boost::algorithm::is_any_of;
      using boost::algorithm::token_compress_on;

      /* Split cubes */
      std::vector<std::string> split_result;
      split(split_result, line, is_any_of("\t "), token_compress_on);

      /* Assign cubes to local variables */
      const std::string& incube = split_result.at(0u);
      std::string outcube = split_result.at(1u);
      boost::replace_all( outcube, "-", "0" );

      /* Calculate number of patterns */
      BDD cube = create_bdd_from_incube(mgr, incube, variables);

      mpz_class patterns(cube.CountMinterm(n));

      /* Update entry in mu */
      if (mu.find(outcube) == mu.end()) {
        mu[outcube] = patterns;
      } else {
        mu[outcube] += patterns;
      }

      /* Update used cubes BDD */
      u |= cube;
    }
  }

  /* Cubes that map to zero */
  std::string zerocube = std::string(m, '0');
  mpz_class zeromu = pow2(n) - mpz_class(u.CountMinterm(n));
  /* It could be that there has been a mapping to 0 in the PLA, just in case */
  if (mu.find(zerocube) == mu.end()) {
    mu[zerocube] = zeromu;
  } else {
    mu[zerocube] += zeromu;
  }

  is.close();

  /* Maximum MU */
  using boost::adaptors::map_values;
  for ( auto v : mu )
  {
#ifdef DEBUG
    std::cout << v.first << " has " << v.second << std::endl;
#endif
  }
  mpz_class maxmu = *boost::max_element(mu | map_values);

  /* Statistics */
  if ( statistics )
  {
    statistics->set( "num_inputs", n );
    statistics->set( "num_outputs", m );
  }

  return calculate_required_lines(n, m, maxmu) - n;
}