Ejemplo n.º 1
0
  // returns true if bit is a useful condition for testing as sufficient
  // (no loop-modified terms, preserves reachability of assert, etc.)
  // regardless of whether it is actually sufficient.
  bool TestBit(Bit *bit)
  {
    Vector<Bit*> &tested_list = propagate->m_sufficient_tested_list;
    Vector<Bit*> &possible_list = propagate->m_sufficient_possible_list;
    Vector<Bit*> &sufficient_list = propagate->m_sufficient_list;

    Solver *solver = state->GetSolver();

    if (tested_list.Contains(bit)) {
      if (possible_list.Contains(bit))
        return true;
      return false;
    }

    if (verbose)
      logout << "SUFFICIENT: " << frame
             << ": Testing " << bit << " [" << bit->Hash() << "]" << endl;

    tested_list.PushBack(bit);

    // don't test for sufficient conditions if a timeout has occurred.
    if (TimerAlarm::ActiveExpired()) {
      if (verbose)
        logout << "SUFFICIENT: " << frame << ": Alarm expired" << endl;
      return false;
    }

    // check that the sufficient condition does not render the point
    // of the assertion unreachable: the solver is still satisfiable after
    // asserting the sufficient condition. this also takes care of
    // unsatisfiable sufficient conditions.

    state->PushContext();

    // ignore bits we can't do any propagation from.

    CheckerPropagate *test_propagate =
      new CheckerPropagate(frame, propagate->m_point,
                           propagate->m_allow_point);
    test_propagate->SetTest(bit);

    // propagations can trigger new solver side conditions. TODO: should figure
    // out what's going on here.
    if (!solver->IsSatisfiable()) {
      state->PopContext();
      return false;
    }

    if (test_propagate->m_where->IsNone()) {
      if (verbose)
        logout << "SUFFICIENT: " << frame << ": Failed propagate: "
               << test_propagate->m_where << endl;
      state->PopContext();
      delete test_propagate;
      return false;
    }

    // assert the tested sufficient holds in the frame.
    frame->AddAssert(bit);

    if (!solver->IsSatisfiable()) {
      // the sufficient condition rendered the assertion point unreachable.
      if (verbose)
        logout << "SUFFICIENT: " << frame
               << ": Renders point unreachable" << endl;

      state->PopContext();
      delete test_propagate;
      return false;
    }

    // this is a good potential sufficient condition, remember it.
    possible_list.PushBack(bit);

    // check whether the bit is actually a sufficient condition.
    // just assert the original negated safe bit, and if it is unsatisfiable
    // it cannot occur under this sufficient condition.

    state->AssertBaseBits();

    bool satisfiable = solver->IsSatisfiable();

    if (verbose) {
      if (satisfiable) {
        logout << "SUFFICIENT: " << frame
               << ": Not a sufficient condition:" << endl;
        solver->PinAssign();
        solver->PrintRawAssignment();
        solver->UnpinAssign();
      }
      else {
        logout << "SUFFICIENT: " << frame << ": Success!" << endl;
      }
    }

    if (!satisfiable) {
      sufficient_list.PushBack(bit);
      propagate_list->PushBack(test_propagate);
    }
    else {
      delete test_propagate;
    }

    state->PopContext();
    return true;
  }