Implemented heuristic
This commit is contained in:
parent
d4e54493c7
commit
9e51fc8c69
@ -28,10 +28,10 @@ public class EightPuzzleNode extends Node<int[][]>
|
||||
{
|
||||
final var successors = new ArrayList<Node<int[][]>>();
|
||||
final var emptyPosition = Objects.requireNonNull(detectEmptyPosition());
|
||||
final int x = emptyPosition.getX();
|
||||
final int y = emptyPosition.getY();
|
||||
final var x = emptyPosition.getX();
|
||||
final var y = emptyPosition.getY();
|
||||
|
||||
for (final Direction dir : Direction.values())
|
||||
for (final var dir : Direction.values())
|
||||
{
|
||||
final var newState = copyOfState();
|
||||
|
||||
@ -50,7 +50,6 @@ public class EightPuzzleNode extends Node<int[][]>
|
||||
{
|
||||
successors.add(successor);
|
||||
}
|
||||
|
||||
}
|
||||
catch (final ArrayIndexOutOfBoundsException ignored)
|
||||
{
|
||||
@ -63,9 +62,9 @@ public class EightPuzzleNode extends Node<int[][]>
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final var builder = new StringBuilder();
|
||||
|
||||
for (final int[] row : super.value)
|
||||
for (final var row : super.value)
|
||||
{
|
||||
builder.append(Arrays.toString(row)).append("\n");
|
||||
}
|
||||
@ -80,9 +79,9 @@ public class EightPuzzleNode extends Node<int[][]>
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int row = 0; row < super.value.length; row++)
|
||||
for (var row = 0; row < super.value.length; row++)
|
||||
{
|
||||
for (int col = 0; col < super.value[row].length; col++)
|
||||
for (var col = 0; col < super.value[row].length; col++)
|
||||
{
|
||||
if (super.value[row][col] != node.value[row][col])
|
||||
{
|
||||
@ -96,9 +95,9 @@ public class EightPuzzleNode extends Node<int[][]>
|
||||
|
||||
private IntPair detectEmptyPosition()
|
||||
{
|
||||
for (int row = 0; row < super.value.length; row++)
|
||||
for (var row = 0; row < super.value.length; row++)
|
||||
{
|
||||
for (int col = 0; col < super.value[row].length; col++)
|
||||
for (var col = 0; col < super.value[row].length; col++)
|
||||
{
|
||||
if (super.value[row][col] == 0)
|
||||
{
|
||||
@ -114,7 +113,7 @@ public class EightPuzzleNode extends Node<int[][]>
|
||||
{
|
||||
final var copy = new int[3][3];
|
||||
|
||||
for (int y = 0; y < copy.length; y++)
|
||||
for (var y = 0; y < copy.length; y++)
|
||||
{
|
||||
System.arraycopy(super.value[y], 0, copy[y], 0, copy.length);
|
||||
}
|
||||
@ -124,15 +123,9 @@ public class EightPuzzleNode extends Node<int[][]>
|
||||
|
||||
private EightPuzzleNode swapStateField(final int[][] newState, final IntPair emptyPos, final IntPair posToSwap)
|
||||
{
|
||||
final int posToSwapX = posToSwap.getX();
|
||||
final int postToSwapY = posToSwap.getY();
|
||||
final int emptyX = emptyPos.getX();
|
||||
final int emptyY = emptyPos.getY();
|
||||
final int tmp;
|
||||
|
||||
tmp = newState[postToSwapY][posToSwapX];
|
||||
newState[postToSwapY][posToSwapX] = newState[emptyY][emptyX];
|
||||
newState[emptyY][emptyX] = tmp;
|
||||
final var tmp = newState[posToSwap.getY()][posToSwap.getX()];
|
||||
newState[posToSwap.getY()][posToSwap.getX()] = newState[emptyPos.getY()][emptyPos.getX()];
|
||||
newState[emptyPos.getY()][emptyPos.getX()] = tmp;
|
||||
|
||||
return new EightPuzzleNode(newState, this);
|
||||
}
|
||||
@ -162,6 +155,5 @@ public class EightPuzzleNode extends Node<int[][]>
|
||||
private enum Direction
|
||||
{
|
||||
TOP, RIGHT, DOWN, LEFT
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package search;
|
||||
|
||||
import search.heuristic.Heuristic;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class Node<T>
|
||||
{
|
||||
@ -14,7 +17,7 @@ public abstract class Node<T>
|
||||
|
||||
protected Node(final T value, final Node<T> parent)
|
||||
{
|
||||
this.value = value;
|
||||
this.value = Objects.requireNonNull(value);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@ -28,6 +31,6 @@ public abstract class Node<T>
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
public abstract boolean isTargetReached(Node<T> target);
|
||||
public abstract boolean isTargetReached(final Node<T> target);
|
||||
public abstract List<Node<T>> generateSuccessors();
|
||||
}
|
||||
|
@ -1,5 +1,39 @@
|
||||
package search.heuristic;
|
||||
|
||||
public class AStar
|
||||
import search.Node;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
public class AStar<T>
|
||||
{
|
||||
private final Heuristic<T> heuristicFunction;
|
||||
|
||||
public AStar(final Heuristic<T> heuristicFunction)
|
||||
{
|
||||
this.heuristicFunction = heuristicFunction;
|
||||
}
|
||||
|
||||
public Node<T> heuristicSearch(final Node<T> start, final Node<T> target)
|
||||
{
|
||||
final var nodes = new PriorityQueue<Node<T>>(Comparator.comparingInt(node -> heuristicFunction.heuristic(node, target)));
|
||||
nodes.add(start);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (nodes.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final var node = nodes.poll();
|
||||
|
||||
if (node.isTargetReached(target))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
nodes.addAll(node.generateSuccessors());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
8
src/search/heuristic/Heuristic.java
Normal file
8
src/search/heuristic/Heuristic.java
Normal file
@ -0,0 +1,8 @@
|
||||
package search.heuristic;
|
||||
|
||||
import search.Node;
|
||||
|
||||
public interface Heuristic<T>
|
||||
{
|
||||
int heuristic(Node<T> node, Node<T> target);
|
||||
}
|
@ -11,7 +11,7 @@ public class BreadthFirstSearch
|
||||
{
|
||||
final var newNodes = new ArrayList<Node<T>>();
|
||||
|
||||
for (final Node<T> node : nodes)
|
||||
for (final var node : nodes)
|
||||
{
|
||||
if (node.isTargetReached(target))
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ public class IterativeDeepening
|
||||
{
|
||||
public <T> Node<T> iterativeDeepening(final Node<T> node, final Node<T> target)
|
||||
{
|
||||
int lowBarrier = 0;
|
||||
var lowBarrier = 0;
|
||||
|
||||
Node<T> resultNode;
|
||||
|
||||
|
@ -1,8 +1,80 @@
|
||||
package search.heuristic;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import search.EightPuzzleNode;
|
||||
import search.Node;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static search.SearchTestUtils.printSolution;
|
||||
|
||||
class AStarTest
|
||||
{
|
||||
@Test
|
||||
void shouldReturnCorrectTargetCubekNodeHeuristik1()
|
||||
{
|
||||
final int[][] state = {
|
||||
{3, 5, 0},
|
||||
{1, 2, 6},
|
||||
{4, 7, 8}
|
||||
};
|
||||
final var root = new EightPuzzleNode(state);
|
||||
|
||||
final int[][] targetState = {
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
{7, 8, 0}
|
||||
};
|
||||
final var expected = new EightPuzzleNode(targetState);
|
||||
|
||||
final var actual = new AStar<>(this::h1).heuristicSearch(root, expected);
|
||||
|
||||
printSolution(actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnCorrectTargetCubekNodeHeuristic2()
|
||||
{
|
||||
final int[][] state = {
|
||||
{2, 0, 4},
|
||||
{6, 7, 1},
|
||||
{8, 5, 3}
|
||||
};
|
||||
final var root = new EightPuzzleNode(state);
|
||||
|
||||
final int[][] targetState = {
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
{7, 8, 0}
|
||||
};
|
||||
final var expected = new EightPuzzleNode(targetState);
|
||||
|
||||
final var actual = new AStar<>(this::h2).heuristicSearch(root, expected);
|
||||
|
||||
printSolution(actual);
|
||||
}
|
||||
|
||||
private int h1(final Node<int[][]> node, final Node<int[][]> target)
|
||||
{
|
||||
final var value = node.getValue();
|
||||
final var targetValue = target.getValue();
|
||||
var counter = 0;
|
||||
|
||||
for (var row = 0; row < value.length; row++)
|
||||
{
|
||||
for (var col = 0; col < value[row].length; col++)
|
||||
{
|
||||
if (value[row][col] != targetValue[row][col])
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
private int h2(final Node<int[][]> node, final Node<int[][]> target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user