patternjavaMinor
Memory efficient A* (AStar) Algorithm
Viewed 0 times
algorithmefficientastarmemory
Problem
I am writing a solved for 15 puzzle game which will find the solution path to any NxN board. For easier boards the algorithm works great solving almost any 3x3 boards, most 4x4 boards, but when I go 5x5 and higher I will often run out of memory. This is the implementation:
I use
`
@WorkerThread
public Solution findPath(Board board){
//Keeps the lowest F value node at the head of queue.
//MinMaxPriorityQueue queue = MinMaxPriorityQueue.orderedBy(new AStarNodeComparator()).maximumSize(1000).create();
PriorityQueue queue = new PriorityQueue<>(1000, new AStarNodeComparator());
Node start = new Node(board, 0, null, heuristic);
Set closeSet = new HashSet<>();
Set openSet = new HashSet<>(); //Set of nodes to be evaluted
queue.add(start);
openSet.add(start.getId());
Node goalNode = null;
long startTime = System.currentTimeMillis();
while(openSet.size() > 0){
Node parent = queue.remove(); //Node that should have lowest f score.
if(parent.getBoardObj().isGoal()) {
goalNode = parent;
break;
}
openSet.remove(parent.getId());
closeSet.add(parent.getId());
for(Node neighborNode :findNeighbors(parent)){
if(!closeSet.contains(neighborNode.getId())){
if(!openSet.contains(neighborNode.getId()) || neighborNode.getFValue() findNeighbors(Node parent){
ArrayList neighbors = new ArrayList<>();
for(int neighbor : parent.getBoardObj().findNeighbors(parent.getBoardObj().getBoard())) {
Board board = new Board(parent.getBoardObj().getBoard(), parent.getBoardObj().getGridSize());
Node neighborNode = new Node(board, parent.getMoves(), parent, heuristic);
parent.getBoardObj().takeMoveAction(neighbor, neighborNode);
neighbors.add(neighborNode);
}
return neighbors;
}I use
getId() as a key to determine if a board is the same or not. This is definitely ideal but best I could think of in a pinch:`
Solution
Bug
This will add a node to the
Did you perhaps mean to say
Then you'd only add it to the
A side effect of that is that you could replace
to something like
if(!openSet.contains(neighborNode.getId()) || neighborNode.getFValue() < parent.getFValue()){
//not in the open set.
openSet.add(neighborNode.getId());
queue.add(neighborNode);
}This will add a node to the
queue twice if its FValue is less than the previous node's FValue. Did you perhaps mean to say
&&?if (!openSet.contains(neighborNode.getId()) && neighborNode.getFValue() < parent.getFValue()){
//not in the open set.
openSet.add(neighborNode.getId());
queue.add(neighborNode);
}Then you'd only add it to the
openSet if it's not in the openSet now and it has a lower FValue. A side effect of that is that you could replace
openSet and closeSet with one queued set. That would save removing and adding on every iteration. You'd only add. You'd also only need one if. You'd also have to change while(openSet.size() > 0){to something like
while (!queue.isEmpty()) {Code Snippets
if(!openSet.contains(neighborNode.getId()) || neighborNode.getFValue() < parent.getFValue()){
//not in the open set.
openSet.add(neighborNode.getId());
queue.add(neighborNode);
}if (!openSet.contains(neighborNode.getId()) && neighborNode.getFValue() < parent.getFValue()){
//not in the open set.
openSet.add(neighborNode.getId());
queue.add(neighborNode);
}while(openSet.size() > 0){while (!queue.isEmpty()) {Context
StackExchange Code Review Q#94484, answer score: 3
Revisions (0)
No revisions yet.