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 successors = new ArrayList<Node<int[][]>>();
|
||||||
final var emptyPosition = Objects.requireNonNull(detectEmptyPosition());
|
final var emptyPosition = Objects.requireNonNull(detectEmptyPosition());
|
||||||
final int x = emptyPosition.getX();
|
final var x = emptyPosition.getX();
|
||||||
final int y = emptyPosition.getY();
|
final var y = emptyPosition.getY();
|
||||||
|
|
||||||
for (final Direction dir : Direction.values())
|
for (final var dir : Direction.values())
|
||||||
{
|
{
|
||||||
final var newState = copyOfState();
|
final var newState = copyOfState();
|
||||||
|
|
||||||
@ -50,7 +50,6 @@ public class EightPuzzleNode extends Node<int[][]>
|
|||||||
{
|
{
|
||||||
successors.add(successor);
|
successors.add(successor);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (final ArrayIndexOutOfBoundsException ignored)
|
catch (final ArrayIndexOutOfBoundsException ignored)
|
||||||
{
|
{
|
||||||
@ -63,9 +62,9 @@ public class EightPuzzleNode extends Node<int[][]>
|
|||||||
@Override
|
@Override
|
||||||
public String toString()
|
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");
|
builder.append(Arrays.toString(row)).append("\n");
|
||||||
}
|
}
|
||||||
@ -80,9 +79,9 @@ public class EightPuzzleNode extends Node<int[][]>
|
|||||||
return false;
|
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])
|
if (super.value[row][col] != node.value[row][col])
|
||||||
{
|
{
|
||||||
@ -96,9 +95,9 @@ public class EightPuzzleNode extends Node<int[][]>
|
|||||||
|
|
||||||
private IntPair detectEmptyPosition()
|
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)
|
if (super.value[row][col] == 0)
|
||||||
{
|
{
|
||||||
@ -114,7 +113,7 @@ public class EightPuzzleNode extends Node<int[][]>
|
|||||||
{
|
{
|
||||||
final var copy = new int[3][3];
|
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);
|
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)
|
private EightPuzzleNode swapStateField(final int[][] newState, final IntPair emptyPos, final IntPair posToSwap)
|
||||||
{
|
{
|
||||||
final int posToSwapX = posToSwap.getX();
|
final var tmp = newState[posToSwap.getY()][posToSwap.getX()];
|
||||||
final int postToSwapY = posToSwap.getY();
|
newState[posToSwap.getY()][posToSwap.getX()] = newState[emptyPos.getY()][emptyPos.getX()];
|
||||||
final int emptyX = emptyPos.getX();
|
newState[emptyPos.getY()][emptyPos.getX()] = tmp;
|
||||||
final int emptyY = emptyPos.getY();
|
|
||||||
final int tmp;
|
|
||||||
|
|
||||||
tmp = newState[postToSwapY][posToSwapX];
|
|
||||||
newState[postToSwapY][posToSwapX] = newState[emptyY][emptyX];
|
|
||||||
newState[emptyY][emptyX] = tmp;
|
|
||||||
|
|
||||||
return new EightPuzzleNode(newState, this);
|
return new EightPuzzleNode(newState, this);
|
||||||
}
|
}
|
||||||
@ -162,6 +155,5 @@ public class EightPuzzleNode extends Node<int[][]>
|
|||||||
private enum Direction
|
private enum Direction
|
||||||
{
|
{
|
||||||
TOP, RIGHT, DOWN, LEFT
|
TOP, RIGHT, DOWN, LEFT
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package search;
|
package search;
|
||||||
|
|
||||||
|
import search.heuristic.Heuristic;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class Node<T>
|
public abstract class Node<T>
|
||||||
{
|
{
|
||||||
@ -14,7 +17,7 @@ public abstract class Node<T>
|
|||||||
|
|
||||||
protected Node(final T value, final Node<T> parent)
|
protected Node(final T value, final Node<T> parent)
|
||||||
{
|
{
|
||||||
this.value = value;
|
this.value = Objects.requireNonNull(value);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +31,6 @@ public abstract class Node<T>
|
|||||||
return this.parent;
|
return this.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean isTargetReached(Node<T> target);
|
public abstract boolean isTargetReached(final Node<T> target);
|
||||||
public abstract List<Node<T>> generateSuccessors();
|
public abstract List<Node<T>> generateSuccessors();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,39 @@
|
|||||||
package search.heuristic;
|
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>>();
|
final var newNodes = new ArrayList<Node<T>>();
|
||||||
|
|
||||||
for (final Node<T> node : nodes)
|
for (final var node : nodes)
|
||||||
{
|
{
|
||||||
if (node.isTargetReached(target))
|
if (node.isTargetReached(target))
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@ public class IterativeDeepening
|
|||||||
{
|
{
|
||||||
public <T> Node<T> iterativeDeepening(final Node<T> node, final Node<T> target)
|
public <T> Node<T> iterativeDeepening(final Node<T> node, final Node<T> target)
|
||||||
{
|
{
|
||||||
int lowBarrier = 0;
|
var lowBarrier = 0;
|
||||||
|
|
||||||
Node<T> resultNode;
|
Node<T> resultNode;
|
||||||
|
|
||||||
|
@ -1,8 +1,80 @@
|
|||||||
package search.heuristic;
|
package search.heuristic;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import search.EightPuzzleNode;
|
||||||
|
import search.Node;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static search.SearchTestUtils.printSolution;
|
||||||
|
|
||||||
class AStarTest
|
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