// function SIMULATED-ANNEALING(problem, schedule) returns a solution state
  // inputs: problem, a problem
  // schedule, a mapping from time to "temperature"
  public List<String> search(Problem p) throws Exception {
    // local variables: current, a node
    // next, a node
    // T, a "temperature" controlling the probability of downward steps
    clearInstrumentation();
    outcome = SearchOutcome.FAILURE;
    lastState = null;
    // current <- MAKE-NODE(INITIAL-STATE[problem])
    Node current = new Node(p.getInitialState());
    Node next = null;
    List<String> ret = new ArrayList<String>();
    // for t <- 1 to INFINITY do
    int timeStep = 0;
    while (true) {
      // temperature <- schedule[t]
      double temperature = scheduler.getTemp(timeStep);
      timeStep++;
      // if temperature = 0 then return current
      if (temperature == 0.0) {
        if (p.isGoalState(current.getState())) {
          outcome = SearchOutcome.SOLUTION_FOUND;
        }
        ret = SearchUtils.actionsFromNodes(current.getPathFromRoot());
        lastState = current.getState();
        break;
      }

      List<Node> children = expandNode(current, p);
      if (children.size() > 0) {
        // next <- a randomly selected successor of current
        next = Util.selectRandomlyFromList(children);
        // /\E <- VALUE[next] - VALUE[current]
        int deltaE = getValue(p, next) - getValue(p, current);

        if (shouldAccept(temperature, deltaE)) {
          current = next;
        }
      }
    }

    return ret;
  }
 private int getHeuristic(Problem p, Node aNode) {
   return p.getHeuristicFunction().getHeuristicValue(aNode.getState());
 }