예제 #1
0
  ASTNode
  STP::callSizeReducing(ASTNode simplified_solved_InputToSAT, BVSolver* bvSolver, const int initial_difficulty_score)
  {
    while (true)
      {
        ASTNode last = simplified_solved_InputToSAT;
        simplified_solved_InputToSAT = sizeReducing(last, bvSolver);
        if (last == simplified_solved_InputToSAT)
          break;
      }

    // Expensive, so only want to do it once.
    if (bm->UserFlags.isSet("bitblast-simplification", "1") && initial_difficulty_score < 250000)
      {
        BBNodeManagerAIG bbnm;
        SimplifyingNodeFactory nf(*(bm->hashingNodeFactory), *bm);
        BitBlaster<BBNodeAIG, BBNodeManagerAIG> bb(&bbnm, simp, &nf , &(bm->UserFlags));
        ASTNodeMap fromTo;
        bb.getConsts(simplified_solved_InputToSAT, fromTo);
        if (fromTo.size() > 0)
          {
            ASTNodeMap cache;
            simplified_solved_InputToSAT = SubstitutionMap::replace(simplified_solved_InputToSAT, fromTo, cache,&nf);
            bm->ASTNodeStats("After bitblast simplification: ", simplified_solved_InputToSAT);
          }
      }
    return simplified_solved_InputToSAT;
  }
예제 #2
0
    // Put anything that's entirely fixed into a from->to map.
    ASTNodeMap
    ConstantBitPropagation::getAllFixed()
    {
      NodeToFixedBitsMap::NodeToFixedBitsMapType::iterator it;

      ASTNodeMap toFrom;

      // iterates through all the pairs of node->fixedBits.
      for (it = fixedMap->map->begin(); it != fixedMap->map->end(); it++)
        {
          const ASTNode& node = (it->first);
          const FixedBits& bits = *it->second;

          // Don't constrain nodes we already know all about.
          if (node.isConstant())
              continue;

          // other nodes will contain the same information (the extract doesn't change the fixings).
          if (BVEXTRACT == node.GetKind() || BVCONCAT == node.GetKind())
            continue;

          if (bits.isTotallyFixed())
            {
              toFrom.insert(std::make_pair(node, bitsToNode(node, bits)));
            }
        }

      return toFrom;
    }
예제 #3
0
파일: STP.cpp 프로젝트: jamesbornholt/stp
ASTNode STP::callSizeReducing(ASTNode inputToSat,
                              BVSolver* bvSolver, PropagateEqualities* pe,
                              const int initial_difficulty_score,
                              int& actualBBSize)
{
  while (true)
  {
    ASTNode last = inputToSat;
    inputToSat = sizeReducing(last, bvSolver, pe);
    if (last == inputToSat)
      break;
  }

  actualBBSize = -1;

  // Expensive, so only want to do it once.
  if (bm->UserFlags.isSet("bitblast-simplification", "1") &&
      initial_difficulty_score < 250000)
  {
    BBNodeManagerAIG bitblast_nodemgr;
    BitBlaster<BBNodeAIG, BBNodeManagerAIG> bb(
        &bitblast_nodemgr, simp, bm->defaultNodeFactory, &(bm->UserFlags));
    ASTNodeMap fromTo;
    ASTNodeMap equivs;
    bb.getConsts(inputToSat, fromTo, equivs);

    if (equivs.size() > 0)
    {
      /* These nodes have equivalent AIG representations, so even though they
       * have different
       * word level expressions they are identical semantically. So we pick one
       * of the ASTnodes
       * and replace the others with it.
       * TODO: I replace with the lower id node, sometimes though we replace
       * with much more
       * difficult looking ASTNodes.
      */
      ASTNodeMap cache;
      inputToSat =
          SubstitutionMap::replace(inputToSat, equivs, cache,
                                   bm->defaultNodeFactory, false, true);
      bm->ASTNodeStats(bb_message.c_str(), inputToSat);
    }

    if (fromTo.size() > 0)
    {
      ASTNodeMap cache;
      inputToSat = SubstitutionMap::replace(
          inputToSat, fromTo, cache, bm->defaultNodeFactory);
      bm->ASTNodeStats(bb_message.c_str(), inputToSat);
    }
    actualBBSize = bitblast_nodemgr.totalNumberOfNodes();
  }
  return inputToSat;
}
예제 #4
0
// idempotent.
ASTNode SubstitutionMap::applySubstitutionMap(const ASTNode& n)
{
  bm->GetRunTimes()->start(RunTimes::ApplyingSubstitutions);
  ASTNodeMap cache;
  ASTNode result = replace(n, *SolverMap, cache, nf, false, false);

// NB. This is an expensive check. Remove it after it's been idempotent
// for a while.
#ifndef NDEBUG
  cache.clear();
  assert(result == replace(result, *SolverMap, cache, nf, false, false));
#endif

  bm->GetRunTimes()->stop(RunTimes::ApplyingSubstitutions);
  return result;
}
예제 #5
0
ASTNode SubstitutionMap::replace(const ASTNode& n, ASTNodeMap& fromTo,
                                 ASTNodeMap& cache, NodeFactory* nf)
{
  if (0 == fromTo.size())
    return n;
  else
    return replace(n, fromTo, cache, nf, false, false);
}
예제 #6
0
  ASTNode
  SubstitutionMap::replace(const ASTNode& n, ASTNodeMap& fromTo, ASTNodeMap& cache, NodeFactory * nf, bool stopAtArrays,
      bool preventInfinite)
  {
    const Kind k = n.GetKind();
    if (k == BVCONST || k == TRUE || k == FALSE)
      return n;

    ASTNodeMap::const_iterator it;

    if ((it = cache.find(n)) != cache.end())
      return it->second;

    if ((it = fromTo.find(n)) != fromTo.end())
      {
      const ASTNode& r = it->second;
      assert(r.GetIndexWidth() == n.GetIndexWidth());

      if (preventInfinite)
        cache.insert(make_pair(n, r));

      ASTNode replaced = replace(r, fromTo, cache, nf, stopAtArrays, preventInfinite);
      if (replaced != r)
        {
          fromTo.erase(n);
          fromTo[n] = replaced;
        }

      if (preventInfinite)
        cache.erase(n);

      cache.insert(make_pair(n, replaced));
      return replaced;
      }

    // These can't be created like regular nodes are
    if (k == SYMBOL)
      return n;

    const unsigned int indexWidth = n.GetIndexWidth();
    if (stopAtArrays && indexWidth > 0) // is an array.
      {
      return n;
      }

    const ASTVec& children = n.GetChildren();
    assert(children.size() > 0);
    // Should have no leaves left here.

    ASTVec new_children;
    new_children.reserve(children.size());

    for (ASTVec::const_iterator it = children.begin(); it != children.end(); it++)
      {
      new_children.push_back(replace(*it, fromTo, cache, nf, stopAtArrays, preventInfinite));
      }

    assert(new_children.size() == children.size());

    // This code short-cuts if the children are the same. Nodes with the same children,
    // won't have necessarily given the same node if the simplifyingNodeFactory is enabled
    // now, but wasn't enabled when the node was created. Shortcutting saves lots of time.
    if (new_children == children)
      {
      cache.insert(make_pair(n, n));
      return n;
      }

    ASTNode result;
    const unsigned int valueWidth = n.GetValueWidth();

    if (valueWidth == 0) // n.GetType() == BOOLEAN_TYPE
      {
      result = nf->CreateNode(k, new_children);
      }
    else
      {
      // If the index and value width aren't saved, they are reset sometimes (??)
      result = nf->CreateArrayTerm(k, indexWidth, valueWidth, new_children);
      }

    // We may have created something that should be mapped. For instance,
    // if n is READ(A, x), and the fromTo is: {x==0, READ(A,0) == 1}, then
    // by here the result will be READ(A,0). Which needs to be mapped again..
    // I hope that this makes it idempotent.

    if (fromTo.find(result) != fromTo.end())
      {
      // map n->result, if running replace() on result gives us 'n', it will not infinite loop.
      // This is only currently required for the bitblast equivalence stuff.
      if (preventInfinite)
        cache.insert(make_pair(n, result));

      result = replace(result, fromTo, cache, nf, stopAtArrays, preventInfinite);
      }

    assert(result.GetValueWidth() == valueWidth);
    assert(result.GetIndexWidth() == indexWidth);

    // If there is already an "n" element in the cache, the maps semantics are to ignore the next insertion.
    if (preventInfinite)
      cache.erase(n);

    cache.insert(make_pair(n, result));
    return result;
  }
예제 #7
0
  //Acceps a query, calls the SAT solver and generates Valid/InValid.
  //if returned 0 then input is INVALID if returned 1 then input is
  //VALID if returned 2 then UNDECIDED
  SOLVER_RETURN_TYPE
  STP::TopLevelSTPAux(SATSolver& NewSolver, const ASTNode& modified_input, const ASTNode& original_input)
  {

    ASTNode inputToSAT = modified_input;
    ASTNode orig_input = original_input;
    bm->ASTNodeStats("input asserts and query: ", inputToSAT);

    ASTNode simplified_solved_InputToSAT = inputToSAT;
    const bool arrayops = containsArrayOps(original_input);

    DifficultyScore difficulty;
    if (bm->UserFlags.stats_flag)
      cerr << "Difficulty Initially:" << difficulty.score(original_input) << endl;

    // A heap object so I can easily control its lifetime.
    BVSolver* bvSolver = new BVSolver(bm, simp);

    simplified_solved_InputToSAT = sizeReducing(inputToSAT, bvSolver);

    unsigned initial_difficulty_score = difficulty.score(simplified_solved_InputToSAT);

    // Fixed point it if it's not too difficult.
    // Currently we discards all the state each time sizeReducing is called,
    // so it's expensive to call.
    if (!arrayops && initial_difficulty_score < 1000000)
      {
        simplified_solved_InputToSAT = callSizeReducing(simplified_solved_InputToSAT, bvSolver, initial_difficulty_score);
        initial_difficulty_score = difficulty.score(simplified_solved_InputToSAT);
      }

    if (bm->UserFlags.stats_flag)
      cout << "Difficulty After Size reducing:" << initial_difficulty_score << endl;

    // Copy the solver map incase we need to revert.
    ASTNodeMap initialSolverMap;
    ASTNode toRevertTo;
    if (!arrayops) // we don't revert for Array problems yet, so don't copy it.
      {
        initialSolverMap.insert(simp->Return_SolverMap()->begin(), simp->Return_SolverMap()->end());
        toRevertTo = simplified_solved_InputToSAT;
      }

    //round of substitution, solving, and simplification. ensures that
    //DAG is minimized as much as possibly, and ideally should
    //garuntee that all liketerms in BVPLUSes have been combined.
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = false;
    bm->start_abstracting = false;
    bm->TermsAlreadySeenMap_Clear();
    do
      {
        inputToSAT = simplified_solved_InputToSAT;

        if (bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT = simp->CreateSubstitutionMap(simplified_solved_InputToSAT, arrayTransformer);

            // Imagine:
            // The simplifier simplifies (0 + T) to T
            // Then bvsolve introduces (0 + T)
            // Then CreateSubstitutionMap decides T maps to a constant, but leaving another (0+T).
            // When we go to simplify (0 + T) will still be in the simplify cache, so will be mapped to T.
            // But it shouldn't be T, it should be a constant.
            // Applying the substitution map fixes this case.
            //
            if (simp->hasUnappliedSubstitutions())
              {
                simplified_solved_InputToSAT = simp->applySubstitutionMap(simplified_solved_InputToSAT);
                simp->haveAppliedSubstitutionMap();
              }

            bm->ASTNodeStats("after pure substitution: ", simplified_solved_InputToSAT);

            simplified_solved_InputToSAT = simp->SimplifyFormula_TopLevel(simplified_solved_InputToSAT, false);

            bm->ASTNodeStats("after simplification: ", simplified_solved_InputToSAT);
          }

        if (bm->UserFlags.wordlevel_solve_flag && bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT = bvSolver->TopLevelBVSolve(simplified_solved_InputToSAT);
            bm->ASTNodeStats("after solving: ", simplified_solved_InputToSAT);
          }
      }
    while (inputToSAT != simplified_solved_InputToSAT);

    if (bm->UserFlags.bitConstantProp_flag)
      {
        bm->GetRunTimes()->start(RunTimes::ConstantBitPropagation);
        SimplifyingNodeFactory nf(*(bm->hashingNodeFactory), *bm);
        simplifier::constantBitP::ConstantBitPropagation cb(simp, &nf, simplified_solved_InputToSAT);
        simplified_solved_InputToSAT = cb.topLevelBothWays(simplified_solved_InputToSAT);

        bm->GetRunTimes()->stop(RunTimes::ConstantBitPropagation);

        if (cb.isUnsatisfiable())
          simplified_solved_InputToSAT = bm->ASTFalse;

        bm->ASTNodeStats("After Constant Bit Propagation begins: ", simplified_solved_InputToSAT);
      }

    if (bm->UserFlags.isSet("use-intervals", "1"))
      {
        EstablishIntervals intervals(*bm);
        simplified_solved_InputToSAT = intervals.topLevel_unsignedIntervals(simplified_solved_InputToSAT);
        bm->ASTNodeStats("After Establishing Intervals: ", simplified_solved_InputToSAT);
      }

    // Find pure literals.
    if (bm->UserFlags.isSet("pure-literals", "1"))
      {
        FindPureLiterals fpl;
        bool changed = fpl.topLevel(simplified_solved_InputToSAT, simp, bm);
        if (changed)
          {
            simplified_solved_InputToSAT = simp->applySubstitutionMap(simplified_solved_InputToSAT);
            simp->haveAppliedSubstitutionMap();
            bm->ASTNodeStats("After Pure Literals: ", simplified_solved_InputToSAT);
          }
      }

    // Simplify using Ite context
    if (bm->UserFlags.optimize_flag && bm->UserFlags.isSet("ite-context", "0"))
      {
        UseITEContext iteC(bm);
        simplified_solved_InputToSAT = iteC.topLevel(simplified_solved_InputToSAT);
        bm->ASTNodeStats("After ITE Context: ", simplified_solved_InputToSAT);
      }

    if (bm->UserFlags.isSet("aig-core-simplify", "0"))
      {
        AIGSimplifyPropositionalCore aigRR(bm);
        simplified_solved_InputToSAT = aigRR.topLevel(simplified_solved_InputToSAT);
        bm->ASTNodeStats("After AIG Core: ", simplified_solved_InputToSAT);
      }

    bm->ASTNodeStats("Before SimplifyWrites_Inplace begins: ", simplified_solved_InputToSAT);

    bm->SimplifyWrites_InPlace_Flag = true;
    bm->Begin_RemoveWrites = false;
    bm->start_abstracting = false;
    bm->TermsAlreadySeenMap_Clear();
    do
      {
        inputToSAT = simplified_solved_InputToSAT;

        if (bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT = simp->CreateSubstitutionMap(simplified_solved_InputToSAT, arrayTransformer);

            if (simp->hasUnappliedSubstitutions())
              {
                simplified_solved_InputToSAT = simp->applySubstitutionMap(simplified_solved_InputToSAT);
                simp->haveAppliedSubstitutionMap();
              }

            bm->ASTNodeStats("after pure substitution: ", simplified_solved_InputToSAT);

            simplified_solved_InputToSAT = simp->SimplifyFormula_TopLevel(simplified_solved_InputToSAT, false);
            bm->ASTNodeStats("after simplification: ", simplified_solved_InputToSAT);


            if (bm->UserFlags.isSet("always-true", "0"))
              {
                SimplifyingNodeFactory nf(*(bm->hashingNodeFactory), *bm);
                AlwaysTrue always (simp,bm,&nf);
                simplified_solved_InputToSAT = always.topLevel(simplified_solved_InputToSAT);
                bm->ASTNodeStats("After removing always true: ", simplified_solved_InputToSAT);
              }
          }

        // The word level solver uses the simplifier to apply the rewrites it makes,
        // without optimisations enabled. It will enter infinite loops on some input.
        // Instead it could use the apply function of the substitution map, but it
        // doesn't yet...
        if (bm->UserFlags.wordlevel_solve_flag && bm->UserFlags.optimize_flag)
          {
            simplified_solved_InputToSAT = bvSolver->TopLevelBVSolve(simplified_solved_InputToSAT);
            bm->ASTNodeStats("after solving: ", simplified_solved_InputToSAT);
          }
      }
    while (inputToSAT != simplified_solved_InputToSAT);

    bm->ASTNodeStats("After SimplifyWrites_Inplace: ", simplified_solved_InputToSAT);

    if (bm->UserFlags.isSet("enable-unconstrained", "1"))
      {
        // Remove unconstrained.
        RemoveUnconstrained r(*bm);
        simplified_solved_InputToSAT = r.topLevel(simplified_solved_InputToSAT, simp);
        bm->ASTNodeStats("After Unconstrained Remove begins: ", simplified_solved_InputToSAT);
      }

    bm->TermsAlreadySeenMap_Clear();

    bm->start_abstracting = false;
    bm->SimplifyWrites_InPlace_Flag = false;
    bm->Begin_RemoveWrites = false;

    long final_difficulty_score = difficulty.score(simplified_solved_InputToSAT);
    if (bm->UserFlags.stats_flag)
      {
        cerr << "Initial Difficulty Score:" << initial_difficulty_score << endl;
        cerr << "Final Difficulty Score:" << final_difficulty_score << endl;
      }

    bool optimize_enabled = bm->UserFlags.optimize_flag;
    if (final_difficulty_score > 1.1 * initial_difficulty_score && !arrayops && bm->UserFlags.isSet(
        "difficulty-reversion", "1"))
      {
        // If the simplified problem is harder, than the
        // initial problem we revert back to the initial
        // problem.

        if (bm->UserFlags.stats_flag)
          cerr << "simplification made the problem harder, reverting." << endl;
        simplified_solved_InputToSAT = toRevertTo;

        // I do this to clear the substitution/solver map.
        // Not sure what would happen if it contained simplifications
        // that haven't been applied.
        simp->ClearAllTables();

        simp->Return_SolverMap()->insert(initialSolverMap.begin(), initialSolverMap.end());
        initialSolverMap.clear();

        // The arrayTransformer calls simplify. We don't want
        // it to put back in all the bad simplifications.
        bm->UserFlags.optimize_flag = false;
      }

    simplified_solved_InputToSAT = arrayTransformer->TransformFormula_TopLevel(simplified_solved_InputToSAT);
    bm->ASTNodeStats("after transformation: ", simplified_solved_InputToSAT);
    bm->TermsAlreadySeenMap_Clear();

    bm->UserFlags.optimize_flag = optimize_enabled;

    SOLVER_RETURN_TYPE res;
    if (bm->UserFlags.arrayread_refinement_flag)
      {
        bm->counterexample_checking_during_refinement = true;
      }

    // We are about to solve. Clear out all the memory associated with caches
    // that we won't need again.
    simp->ClearCaches();
    simp->haveAppliedSubstitutionMap();
    bm->ClearAllTables();

    // Deleting it clears out all the buckets associated with hashmaps etc. too.
    delete bvSolver;
    bvSolver = NULL;

    if (bm->UserFlags.stats_flag)
      simp->printCacheStatus();

    const bool maybeRefinement = arrayops && bm->UserFlags.arrayread_refinement_flag;

    simplifier::constantBitP::ConstantBitPropagation* cb = NULL;
    std::auto_ptr<simplifier::constantBitP::ConstantBitPropagation> cleaner;

    if (bm->UserFlags.bitConstantProp_flag)
      {
        bm->ASTNodeStats("Before Constant Bit Propagation begins: ", simplified_solved_InputToSAT);

        bm->GetRunTimes()->start(RunTimes::ConstantBitPropagation);
        cb = new simplifier::constantBitP::ConstantBitPropagation(simp, bm->defaultNodeFactory,
            simplified_solved_InputToSAT);
        cleaner.reset(cb);
        bm->GetRunTimes()->stop(RunTimes::ConstantBitPropagation);

        if (cb->isUnsatisfiable())
          simplified_solved_InputToSAT = bm->ASTFalse;
      }

    ToSATAIG toSATAIG(bm, cb);
    toSATAIG.setArrayTransformer(arrayTransformer);

    ToSATBase* satBase = bm->UserFlags.isSet("traditional-cnf", "0") ? tosat : ((ToSAT*) &toSATAIG) ;

    // If it doesn't contain array operations, use ABC's CNF generation.
    res = Ctr_Example->CallSAT_ResultCheck(NewSolver, simplified_solved_InputToSAT, orig_input, satBase,
        maybeRefinement);

    if (SOLVER_UNDECIDED != res)
      {
        // If the aig converter knows that it is never going to be called again,
        // it deletes the constant bit stuff before calling the SAT solver.
        if (toSATAIG.cbIsDestructed())
          cleaner.release();

        CountersAndStats("print_func_stats", bm);
        return res;
      }

    assert(arrayops); // should only go to abstraction refinement if there are array ops.
    assert(bm->UserFlags.arrayread_refinement_flag); // Refinement must be enabled too.

    // Unfortunately how I implemented the incremental CNF generator in ABC means that
    // cryptominisat and simplifying minisat may simplify away variables that we later need.

    res = Ctr_Example->SATBased_ArrayReadRefinement(NewSolver, simplified_solved_InputToSAT, orig_input, satBase);
    if (SOLVER_UNDECIDED != res)
      {
        if (toSATAIG.cbIsDestructed())
          cleaner.release();

        CountersAndStats("print_func_stats", bm);
        return res;
      }

    res = Ctr_Example->SATBased_ArrayWriteRefinement(NewSolver, orig_input, satBase);
    if (SOLVER_UNDECIDED != res)
      {
        if (toSATAIG.cbIsDestructed())
          cleaner.release();

        CountersAndStats("print_func_stats", bm);
        return res;
      }

    res = Ctr_Example->SATBased_ArrayReadRefinement(NewSolver, simplified_solved_InputToSAT, orig_input, satBase);
    if (SOLVER_UNDECIDED != res)
      {
        if (toSATAIG.cbIsDestructed())
          cleaner.release();

        CountersAndStats("print_func_stats", bm);
        return res;
      }

//    if (!bm->UserFlags.num_absrefine_flag)
      {
        FatalError("TopLevelSTPAux: reached the end without proper conclusion:"
          "either a divide by zero in the input or a bug in STP");
        //bogus return to make the compiler shut up
        return SOLVER_ERROR;
      }
  //  else
      {
       // return res;
      }
  } //End of TopLevelSTPAux
예제 #8
0
    // NB: This expects that the constructor was called with teh same node. Sorry.
    ASTNode
    ConstantBitPropagation::topLevelBothWays(const ASTNode& top)
    {
      assert(top.GetSTPMgr()->UserFlags.bitConstantProp_flag);
      assert (BOOLEAN_TYPE == top.GetType());

      propagate();
      status = NO_CHANGE;

      //Determine what must always be true.
      ASTNodeMap fromTo = getAllFixed();

      if (debug_cBitProp_messages)
        {
          cerr << "Number removed by bottom UP:" << fromTo.size() << endl;
        }

      setNodeToTrue(top);

      if (debug_cBitProp_messages)
        {
          cerr << "starting propagation" << endl;
          printNodeWithFixings();
          cerr << "Initial Tree:" << endl;
          cerr << top;
        }

      propagate();

      if (debug_cBitProp_messages)
        {
          cerr << "status:" << status <<endl;
          cerr << "ended propagation" << endl;
          printNodeWithFixings();
        }

      // propagate may have stopped with a conflict.
      if (CONFLICT == status)
          return top.GetSTPMgr()->CreateNode(FALSE);

      ASTVec toConjoin;

      // go through the fixedBits. If a node is entirely fixed.
      // "and" it onto the top. Creates redundancy. Check that the
      // node doesn't already depend on "top" directly.

      for (NodeToFixedBitsMap::NodeToFixedBitsMapType::iterator it = fixedMap->map->begin(); it != fixedMap->map->end(); it++) // iterates through all the pairs of node->fixedBits.
        {
          const FixedBits& bits = *it->second;

          if (!bits.isTotallyFixed())
            continue;

          const ASTNode& node = (it->first);

          // Don't constrain nodes we already know all about.
          if (node.isConstant())
            continue;

          // other nodes will contain the same information (the extract doesn't change the fixings).
          if (BVEXTRACT == node.GetKind() || BVCONCAT == node.GetKind())
            continue;

          // toAssign: conjoin it with the top level.
          // toReplace: replace all references to it (except the one conjoined to the top) with this.
          ASTNode propositionToAssert;
          ASTNode constantToReplaceWith;
          // skip the assigning and replacing.
          bool doAssign = true;

            {
              // If it is already contained in the fromTo map, then it's one of the values
              // that have fully been determined (previously). Not conjoined.
              if (fromTo.find(node) != fromTo.end())
                continue;

              ASTNode constNode = bitsToNode(node,bits);

              if (node.GetType() == BOOLEAN_TYPE)
                {
                  if (SYMBOL == node.GetKind())
                    {
                      bool r = simplifier->UpdateSubstitutionMap(node, constNode);
                      assert(r);
                      doAssign = false;
                    }
                  else if (bits.getValue(0))
                    {
                      propositionToAssert = node;
                      constantToReplaceWith = constNode;
                    }
                  else
                    {
                      propositionToAssert = nf->CreateNode(NOT, node);
                      constantToReplaceWith = constNode;
                    }
                }
              else if (node.GetType() == BITVECTOR_TYPE)
                {
                  assert(((unsigned)bits.getWidth()) == node.GetValueWidth());
                  if (SYMBOL == node.GetKind())
                    {
                      bool r = simplifier->UpdateSubstitutionMap(node, constNode);
                      assert(r);
                      doAssign = false;
                    }
                  else
                    {
                      propositionToAssert = nf->CreateNode(EQ, node, constNode);
                      constantToReplaceWith = constNode;
                    }
                }
              else
                FatalError("sadf234s");
            }

          if (doAssign && top != propositionToAssert
              && !dependents->nodeDependsOn(top, propositionToAssert))
            {
              assert(!constantToReplaceWith.IsNull());
              assert(constantToReplaceWith.isConstant());
              assert(propositionToAssert.GetType() == BOOLEAN_TYPE);
              assert(node.GetValueWidth() == constantToReplaceWith.GetValueWidth());

              fromTo.insert(make_pair(node, constantToReplaceWith));
              toConjoin.push_back(propositionToAssert);
            }
        }

     // Write the constants into the main graph.
      ASTNodeMap cache;
      ASTNode result = SubstitutionMap::replace(top, fromTo, cache,nf);

      if (0 != toConjoin.size())
        {
          // It doesn't happen very often. But the "toConjoin" might contain a variable
          // that was added to the substitution map (because the value was determined just now
          // during propagation.
          ASTNode conjunct = (1 == toConjoin.size())? toConjoin[0]: nf->CreateNode(AND,toConjoin);
          conjunct = simplifier->applySubstitutionMap(conjunct);

          result = nf->CreateNode(AND, result, conjunct); // conjoin the new conditions.
        }


  	if (debug_print_graph_after)
		{
			ofstream file;
			file.open("afterCbitp.gdl");
			PrintingHackfixedMap = fixedMap;
			printer::GDL_Print(file,top,&toString);
			file.close();
		}


      assert(BVTypeCheck(result));
      assert(status != CONFLICT); // conflict should have been seen earlier.
      return result;
    }