public void solve(T start, T target) {
    reset();

    Set<T> visited = new HashSet<T>();
    SearchNode best = new SearchNode(null, start, target);
    Queue<SearchNode> openList = new PriorityQueue<>();
    openList.add(best);
    solutionFound = false;
    while (openList.size() > 0 && !solutionFound) {
      best = openList.poll();
      if (debug) {
        System.out.println("best: " + best.getObject());
      }
      if (!visited.contains(best.getObject())) {
        visited.add(best.getObject());
        if (best.getObject().achieves(target)) {
          solutionFound = true;
        } else {
          addSuccessors(best, openList, target);
        }
      }
    }

    if (solutionFound) {
      reconstructMoves(best);
    }
  }
 private void addSuccessors(SearchNode best, Queue<SearchNode> openList, T target) {
   for (T p : best.getObject().getSuccessors()) {
     numNodes++;
     SearchNode newNode = new SearchNode(best, p, target);
     depth = Math.max(newNode.getDepth(), depth);
     openList.add(newNode);
   }
 }
  private void reconstructMoves(SearchNode searcher) {
    while (searcher != null) {
      solution.add(searcher.getObject());
      searcher = searcher.getParent();
    }

    for (int i = 0; i < solution.size() / 2; ++i) {
      T temp = solution.get(i);
      int other = solution.size() - i - 1;
      solution.set(i, solution.get(other));
      solution.set(other, temp);
    }
  }