public static<E> Path<E> findPath(PathFinderSpecializer<E> specializer,
                                                                          Collection<Path<E>> starts,
                                                                          Collection<E> goals) {

                PriorityQueue<Path<E>> active =
                        new PriorityQueue<Path<E>>(starts.size(), specializer);
                Set<E> finished = new HashSet<E>();
                for (Path<E> n: starts) {
                        active.add(n);
                }

                // Go while there are still nodes left to explore
                while (!active.isEmpty()) {
                        Path<E> path = active.poll();
                        E node = path.end();

                        // If we reached a goal then we are done
                        if (goals.contains(node))
                                return path;

                        finished.add(node);

                        for (E n: specializer.expandNode(node)){
                                if (!finished.contains(n)){
                                        boolean isActive = false;
                                        for (Path<E> p: active)
                                                if (n.equals(p.end())){
                                                        isActive = true;
                                                        break;
                                                }
                                        // If a child node is not already in finished or active
                                        // lists, then add to our active queue
                                        if (!isActive){
                                                active.add(path.extend(n));
                                        }
                                }
                        }
                }

                return null;
        }