After I completed the how to make a A* pathfinding I wanted to learn more about Jump Point Search.
I did some reasearch how to make one by reading the
orginal paper about it.
So after reading it a couple of times I try it for myself so I made one and it works short of.
so the problem is that he can find a path but not in the most best way see images what I mean.
So my first thought was that I did something wrong with the lowest Fcost so try to change that first but that was not answer. then I looked into the Sucessor function if I did something wrong try to change the order of the script but the result stay the same.
after that I looked into the jump code. But to be honest I don't see it what I did wrong either.
Then I try to find the answer here but, most of the answers resluted in the same result.
Maybe it can be that I have forgot something that this algoritme needs.
sucessor function.
List<Node> IDSucessor(Node currentNode,Node start,Node goal)
{
List<Node> sucessors = new List<Node>();
List<Node> neighbors = new List<Node>();
neighbors = Neigbors(currentNode);
foreach (Node n in neighbors)
{
Node node = n;
node = Jump(currentNode, n.x - currentNode.x, n.y - currentNode.y, start, goal);
if (node != null)
{
if (!closedList.Contains(node))
{
int newMovementCost = (int)currentNode.GCost + GetDistance(currentNode, n);
if (newMovementCost < node.GCost || !openList.Contains(node))
{
node.GCost = newMovementCost;
node.HCost = GetDistance(n, goal);
node.FCost = n.GCost + n.HCost;
node.parent = currentNode;
if (!openList.Contains(node))
{
sucessors.Add(node);
}
}
}
}
}
return sucessors;
}
Jump Function
Node Jump(Node currentNode,int x,int y,Node start,Node goal)
{
Node n = RetunNodeDir(currentNode, x, y);
if (n==null)
{
//if n is null return null
return null;
}
if (n.Col)
{
//if n collider return null.
return null;
}
if (n.x == goal.x && n.y==goal.y)
{
//if it's a goal then the n will be a sucessor
goalFounded = true;
return n;
}
//if A neigbor is forced than return n as it's sucessor.
if (IsForced(n, x, y, start, goal))
{
return n;
}
//if diangle
if(x!=0 && y!=0)
{
if (IsForecedDiangle(n, x, y, start, goal))
{
return n;
}
if (Jump(n, x, 0, start, goal) != null || Jump(n, 0, y, start, goal) != null)
{
return n;
}
}
//jump again
return Jump(n, x, y, start, goal);
}
Force node horizontal. the vertical is the same code but has a diffrent coordination direction. the diangle use also the same code but it needed a extra agrument in the function.
bool IsForcedHor(Node currentNode,int dirX)
{
Node up = RetunNodeDir(currentNode, 0, 1);
Node down = RetunNodeDir(currentNode, 0, - 1);
if(up!=null)
{
if(up.Col)
{
//check next to him.
Node upNext = RetunNodeDir(currentNode, dirX, 1);
if(upNext!=null)
{
if(!upNext.Col)
{
return true;
}
}
}
}
if(down!=null)
{
if(down.Col)
{
Node downNext = RetunNodeDir(currentNode, dirX, - 1);
if (downNext != null)
{
if (!downNext.Col)
{
return true;
}
}
}
}
return false;
}
I hope I gave you enough information.
kind regards,
codinG
Related
I am trying to implement Iterative Deeping Search. I do not know what I am doing wrong, but I don't seem to be getting it right. I always end up with an infinite loop.
Can anyone point out my mistake?
I implemented the Depth-Limited Search and used it in my IDS code. DLS seems to be working fine on its own, but I do not understand IDS and why i'm ending up in an infinite loop.
public class IterativeDeepeningSearch<T> where T : IComparable
{
string closed;
public int maximumDepth;
public int depth = 0;
bool Found = false;
Stack<Vertex<T>> open;
public IterativeDeepeningSearch()
{
open = new Stack<Vertex<T>>();
}
public bool IDS(Vertex<T> startNode, Vertex<T> goalNode)
{
// loops through until a goal node is found
for (int _depth = 0; _depth < Int32.MaxValue; _depth++)
{
bool found = DLS(startNode, goalNode, _depth);
if (found)
{
return true;
}
}
// this will never be reached as it
// loops forever until goal is found
return false;
}
public bool DLS(Vertex<T> startNode, Vertex<T> goalNode, int _maximumDepth)
{
maximumDepth = _maximumDepth;
open.Push(startNode);
while (open.Count > 0 && depth < maximumDepth)
{
Vertex<T> node = open.Pop();
closed = closed + " " + node.Data.ToString();
if (node.Data.ToString() == goalNode.Data.ToString())
{
Debug.Write("Success");
Found = true;
break;
}
List<Vertex<T>> neighbours = node.Neighbors;
depth++;
if (neighbours != null)
{
foreach (Vertex<T> neighbour in neighbours)
{
if (!closed.Contains(neighbour.ToString()))
open.Push(neighbour);
}
Debug.Write("Failure");
}
}
Console.WriteLine(closed);
return Found;
}
}
}
PS: My Vertex Class just has two properties, Data and Children
The for loop iterates on _depth but in the DLS function you are passing depth, which is always 0
for (int _depth = 0; _depth < Int32.MaxValue; _depth++)
{
bool found = DLS(startNode, goalNode, depth);
if (found)
{
return true;
}
}
I was studying search algorithms and wanted to solve the missionaries and cannibals problem in order to practice. However, my code never provides a solution. At first, I thought this was because I had recurring states, causing an infinite loop, so I added a state history to make sure states weren't being repeated. However, this still has not worked.
Below is the code I have written. I am using vectors to represent the states of the missionaries, cannibals and the boat and the children of the nodes get added if they pass a check that checks if the move is within the range (0,0,0) and (3,3,1).
I have tried stepping through the code but since the tree is fairly large I can only keep track of so many things, so I have a hard time seeing the fault in my code.
This was written in Visual Studio as a console program.
Vector3 class
public class Vector3
{
public int m;
public int c;
public int b;
public Vector3(int M, int C, int B)
{
m = M;
c = C;
b = B;
}
public override bool Equals(System.Object obj)
{
if (obj == null)
return false;
Vector3 p = obj as Vector3;
if ((System.Object)p == null)
return false;
return (m == p.m) && (c == p.c) && (b == p.b);
}
}
Node class
public class Node
{
public Vector3 State;
public Node(Vector3 st)
{
State = st;
}
}
My Program.cs
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.DFS(new Node(new Vector3(3, 3, 1)));
Console.ReadKey();
}
List<Vector3> History = new List<Vector3>();
Vector3[] Operators = new Vector3[]
{
new Vector3(1,0,1),
new Vector3(2,0,1),
new Vector3(0,1,1),
new Vector3(0,2,1),
new Vector3(1,1,1),
};
public bool TryMove(Vector3 current, Vector3 toApply, bool substract)
{
if (substract)
{
if (current.c - toApply.c < 0 || current.m - toApply.m < 0 || current.b - toApply.b < 0 || (current.c - toApply.c) > (current.m - toApply.m))
{
return false;
}
else return true;
}
else
{
if (current.c + toApply.c > 3 || current.m + toApply.m > 3 || current.b + toApply.b > 1 || (current.c + toApply.c) > (current.m + toApply.m))
{
return false;
}
else return true;
}
}
public void DFS(Node n)
{
Stack<Node> stack = new Stack<Node>();
stack.Push(n);
while (stack.Count > 0)
{
Node curNode = stack.Pop();
if (History.Contains(curNode.State))
{
}
else
{
History.Add(curNode.State);
if (curNode.State == new Vector3(0, 0, 0))
{
Console.WriteLine("Solution found.");
return;
}
else
{
if (curNode.State.b == 0) //Boat is across the river
{
for (int x = 0; x < 5; x++)
{
if (TryMove(curNode.State, Operators[x], false))
{
stack.Push(new Node(new Vector3(curNode.State.m + Operators[x].m, curNode.State.c + Operators[x].c, curNode.State.b + Operators[x].b)));
}
}
}
else //Boat == 1
{
for (int x = 0; x < 5; x++)
{
if (TryMove(curNode.State, Operators[x], true))
{
stack.Push(new Node(new Vector3(curNode.State.m - Operators[x].m, curNode.State.c - Operators[x].c, curNode.State.b - Operators[x].b)));
}
}
}
}
}
}
Console.WriteLine("No solution found.");
return;
}
}
My code keeps hitting the 'No solution found' block. When I remove the history I keep infinite looping between states (3,3,1) and (2,2,1) and get an OutOfMemoryException at the 2 gigabyte mark, so I'm not even sure about keeping track of history anymore.
What steps should I take in order to implement the DFS in the context of the problem correctly, given the code I provided above?
Your algorithm is fine. The problem is that you used == operator in curNode.State == new Vector3(0, 0, 0); line. In C#, by default, == compares objects by reference, so this condition will always return false. Either use node.State.Equals(new Vector3(0, 0, 0)) or override == operator to use your Equals method.
See MSDN Guidelines on custom comparison in C#.
I'm trying to write an algorithm that will take a list of points visited along an edge, and a list of unvisited edges (made up of pairs of points) which make up the rest of the object and search through them for a path that completes the edge (that is, connects the start to the end). I currently have:
public static int PolygonSearch(Point start, Point end, List<Point> visitedPoints, List<Point[]> unvisitedEdges)
{
int count = 0;
for (int i = unvisitedEdges.Count - 1; i > -1; i--)
{
Point[] line = unvisitedEdges[i];
if (((Equal(line[0], start) && Equal(line[1], end))
|| (Equal(line[1], start) && Equal(line[0], end)))
&& visitedPoints.Count > 2)
{
return count + 1;
}
else if (Equal(start, line[0]))
{
unvisitedEdges.RemoveAt(i);
count += PolygonSearch(line[1], end, visitedPoints, unvisitedEdges);
}
else if (Equal(start, line[1]))
{
unvisitedEdges.RemoveAt(i);
count += PolygonSearch(line[0], end, visitedPoints, unvisitedEdges);
}
}
return count;
}
(start and end being the current start and end points of the line)
The obvious problem here is the removal, which messes up the outer loops, but I'm not sure how to correct for it, I tried creating a new list each time but that didn't work (I've not even implemented a way to return the path yet, just to count the valid ones).
Any help fixing this would be greatly appreciated.
To avoid removing an object, you can set it as 'removed', then ignore it if it is so set.
The following uses a flag called Visited. If it is 'removed', Visited is set to true.
I haven't tested this obviously, but it should give you a general idea of what to do:
public struct Edge
{
public Edge()
{
this.Visited = false;
}
public Point[] Points;
public bool Visited;
}
public static int PolygonSearch(Point start, Point end, List<Point> visitedPoints, List<Edge> unvisitedEdges)
{
int count = 0;
for (int i = unvisitedEdges.Count - 1; i > -1; i--)
{
Edge line = unvisitedEdges[i];
if (((Equal(line.Points[0], start) && Equal(line.Points[1], end))
|| (Equal(line.Points[1], start) && Equal(line.Points[0], end)))
&& visitedPoints.Count > 2
&& line.Visited == false)
{
return count + 1;
}
else if (Equal(start, line[0]))
{
unvisitedEdges[i].Visited = true;
count += PolygonSearch(line.Points[1], end, visitedPoints, unvisitedEdges);
}
else if (Equal(start, line[0]))
{
unvisitedEdges[i].Visited = true;
count += PolygonSearch(line.Points[1], end, visitedPoints, unvisitedEdges);
}
}
return count;
}
The method in JavaScript is:
findNode: function(root, w, h) {
if (root.used)
return this.findNode(root.right, w, h) || this.findNode(root.down, w, h);
else if ((w <= root.w) && (h <= root.h))
return root;
else
return null;
}
this line in particular wont work in C#
return this.findNode(root.right, w, h) || this.findNode(root.down, w, h);
This is my attempt at translating it but I could use a second opinion as to whether this will work or break the algorithm. Is there a better way that I'm missing?
private Node FindNode(Node node, Block block)
{
Node n;
if (node.used) // recursive case
{
// is this a good translation of the JavaScript one-liner?
n = FindNode(node.right, block);
if (n != null)
{
return n;
}
else
{
return FindNode(node.down, block);
}
}
else if ((block.width <= node.width) && (block.height <= node.height)) // Base case
{
return node;
}
else
{
return null;
}
}
Here is the original algorithm I'm working off of.
n = FindNode(node.right, block);
return n ?? FindNode(node.down, block);
would be the only change I would make
public void HeightIterative()
{
int counter = 0;
int counter2 = 0;
TreeNode current=root;
if(current != null)
{
while(current.LeftNode!=null)
{
counter++;
current = current.LeftNode;
}
while(current.RightNode!=null)
{
counter2++;
current = current.RightNode;
}
}
int res = 1+Math.Max(counter, counter2);
Console.WriteLine("The Height Of Tree Is: "+res);
}
I wrote iterative method, to calculate height of tree. but in some cases its not working properly. As in case:
10
1
2
3
4
5
18
17
16
15
14
13
what's the problem. according to this sequence height of tree is 6 where as my code is showing 5.
You are using two loops, but each loop investigated only oneside of node, but each node in tree has two sides you should investigate it all. You can do it through recursion call.
private int GetLen(TreeNode node)
{
var result = 0;
if(node != null)
{
result = Math.Max(GetLen(node.LeftNode), GetLen(node.RightNode)) + 1;
}
return result;
}
public void HeightIterative()
{
int res = GetLen(root);
Console.WriteLine("The Height Of Tree Is: "+res);
}
Iterative version:
private class NodeInfo
{
public NodeInfo(TreeNode node, int len)
{
Node = node;
Len = len;
}
public TreeNode Node {get; private set;}
public int Len {get; private set;}
}
public void HeightIterative()
{
int maxLen = 0;
var queue = new Queue<NodeInfo>();
queue.Enqueue(new NodeInfo(root, 1));
while (queue.Count > 0)
{
var item = queue.Dequeue();
var current = item.Node;
var currentLen = item.Len;
if (current.LeftNode != null)
{
queue.Enqueue(new NodeInfo(current.LeftNode, currentLen + 1));
}
if (current.RightNode != null)
{
queue.Enqueue(new NodeInfo(current.RightNode, currentLen + 1));
}
if (currentLen > maxLen)
{
maxLen = currentLen;
}
}
Console.WriteLine("The Height Of Tree Is: " + maxLen);
}
There is a way that does not require any extra space except the queue for storing the nodes.
Add child nodes of a current element and remember size of the queue.
Let each dequeue call decrement the counter
When counter reaches zero that means we are done with current level.
Repeat and count number of times counter reaches zero - this is the depth/height of the tree
Code goes like this :
public int treeDepth(Node root){
int height = 0;
int counterNodesInLevel = 1;
if(root!=null)
{
Queue<Node> queue=new Queue<Node>()
queue.enqueue(root);
while (!queue.isEmpty()){
Node current = queue.dequeue();
counterNodesInLevel -= 1;
if(current.left!=null){
queue.enqueue(current.left)
}
if(current.right!=null){
queue.enqueue(current.right)
}
if (counterNodesInLevel == 0){
height += 1;
counterNodesInLevel = queue.Size();
}
}
}
return height;
}
Time complexity is O(N), space complexity is O(N)
The problem:
You are finding the depth of the left-most node in the first loop, and the right-most in the second, and never interrogating any node that involves going down to the left AND the right.
A solution:
Have a single loop that drills down the left nodes, but adds each right node that it 'skips' into a queue. When you run out of left nodes, pop-off a node form your queue and continue on until the queue becomes empty. You'll need to store the height of each node you put in the queue with that node.
public int Height()
{
int result = GetMaxHeight(this.Root,0);
return result;
}
private int GetMaxHeight(Node<T> node,int count)
{
int leftMax = 0, rightMax = 0;
if (node.Left != null)
{
leftMax = GetMaxHeight(node.Left, count+1);
}
if (node.Right != null)
{
rightMax = GetMaxHeight(node.Right, count + 1);
}
if(node.Left==null && node.Right == null)
{
return count;
}
return Math.Max(leftMax,rightMax);
}