Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A* Algorithm while solving Sliding Tile puzzle executes for a very long time

While trying to run the code for 24 Tile puzzle and above, the code executes for a very long time (Greater than 3 minutes) (It runs pretty quick for 8 Tile puzzle). The code can be found below.

while (openQueue.isEmpty() == false) {
    State queueHead = openQueue.remove();
    openMap.remove(queueHead.hashCode());
    closedMap.put(queueHead.hashCode(), queueHead);
    State queueHeadState = queueHead;

    if (Constants.debug) {
        System.out.println("Popped State");
        HeuristicSolverUtility.printState(queueHead);   
    }
    // If reached goal state . Termination condition.
    if (queueHead.equals(goalState)) {
        break;
    } else {
        List<Action> listOfPossibleActions = queueHeadState
                .getPossibleActions();
        Iterator<Action> actIter = listOfPossibleActions.iterator();
        while (actIter.hasNext()) {
            // Here it performs Tile UP, DOWN, LEFT and RIGHT operations 
            Action actionOnState = actIter.next();
            StateP newState = actionOnState.applyTo(queueHeadState);
            newState.setHeuristicCost((double) ManhattanDistance
                    .calculate(newState));
            newState.setParent(queueHead);
            newState.setAction(actionOnState);

            if (!closedMap.containsKey(newState.hashCode()) && !openMap.containsKey(newState.hashCode())) {
                openQueue.offer(newState);
                openMap.put(newState.hashCode(), newState);
            } else if (openMap.containsKey(newState.hashCode())) {
                System.out.println("State found in Open Map");
                State stateFetchedFromOpenMap = openMap.get(newState.hashCode());
                if (stateFetchedFromOpenMap.getPathCost() > newState.getPathCost()) {
                    openMap.remove(stateFetchedFromOpenMap.hashCode());
                    openMap.put(newState.hashCode(), newState);
                    openQueue.remove(stateFetchedFromOpenMap);
                    openQueue.add(newState);
                }
            }
        }
    }
}

This is my hashcode :

    @Override
    public int hashCode() {
        return Arrays.hashCode(allCells);       
    }

And this is the code for Priority Queue comparator :-

public static class HeuristicComparator implements Comparator<State> {
    public int compare(State o1, State o2) {
        Double result;

        result = o1.getKey() - o2.getKey();
        if (result == 0.0) {
            // Ties among minimal f values are resolved in favor of the
            // deepest node in the search tree
            // i.e. the closest node to the goal
            result = (double) (o2.getPathCost() - o1.getPathCost());
        }
        if (result > 0.0) {
            return 1;
        }
        return -1;
    }
}

I am not sure why does it take so long for my A* implementation to compute for 24 tile puzzle and up. How can I optimize my code to compute faster, also is there any bug that is causing it to take so long?

If you are interested in the entire code, it can be found here

like image 815
aaditya chauhan Avatar asked Dec 05 '25 10:12

aaditya chauhan


2 Answers

As Turing85 has mentioned, this is an NP-complete problem, so it's unlikely that you will have a fast runtime.

I would suggest that you can do the following:

  1. Try to use different heuristic
  2. Try to use bidirectional search
like image 53
Ivan Mushketyk Avatar answered Dec 08 '25 12:12

Ivan Mushketyk


I know this is an old question, but I just had the same problem.

Apparently, Arrays.hashCode(allCells); is really really slow, and using another hash code can make the algorithm run much faster.

Try this answer for alternative hash.

like image 22
nogmos Avatar answered Dec 08 '25 14:12

nogmos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!