Advertisement

A* scanning extra nodes?

Started by March 26, 2015 03:04 PM
22 comments, last by polyfrag 9 years, 6 months ago

Two thoughts:
1) Is that a floating point Vector2? If that's your custom one, you might want to double check the comparison operator
2) Toss some parenthesis around that if, though I think it should be okay without them, if you're not getting in there, maybe that's the problem.
(OpenList.SingleOrDefault(node => node.Position == Neighbor.Position).G_Vaule + G_Score) < CurrentNode.G_Vaule

Also, why are you doing the if elseif above it, it looks like you have if(A) else if(!A), couldn't that just be if(A) else {//not A implied}


1) Yes, It's a floating point Vector2. Its not my custom class. Its in MonoGame/XNA.
2)I'm 100% sure that this line is the problem. I just don't know how to fix it.

Yeah true. It could be just if(A) else. But when I debugging I wanted things to be explicit. Idk.

I'm looking at the Wiki Pseudocode and I think i'm lost at this part.


tentative_g_score := g_score[current] + dist_between(current,neighbor)
if neighbor not in openset or tentative_g_score < g_score[neighbor] 


This is the full code


function A*(start,goal)
    closedset := the empty set    // The set of nodes already evaluated.
    openset := {start}    // The set of tentative nodes to be evaluated, initially containing the start node
    came_from := the empty map    // The map of navigated nodes.
 
    g_score[start] := 0    // Cost from start along best known path.
    // Estimated total cost from start to goal through y.
    f_score[start] := g_score[start] + heuristic_cost_estimate(start, goal)
 
    while openset is not empty
        current := the node in openset having the lowest f_score[] value
        if current = goal
            return reconstruct_path(came_from, goal)
 
        remove current from openset
        add current to closedset
        for each neighbor in neighbor_nodes(current)
            if neighbor in closedset
                continue
            tentative_g_score := g_score[current] + dist_between(current,neighbor)
 
            if neighbor not in openset or tentative_g_score < g_score[neighbor] 
                came_from[neighbor] := current
                g_score[neighbor] := tentative_g_score
                f_score[neighbor] := g_score[neighbor] + heuristic_cost_estimate(neighbor, goal)
                if neighbor not in openset
                    add neighbor to openset
 
    return failure
 
function reconstruct_path(came_from,current)
    total_path := [current]
    while current in came_from:
        current := came_from[current]
        total_path.append(current)
    return total_path

Well, one thing to watch out for is floating point comparison, depending on how you set up your vectors, they may never actually be equal. You should probably swap to integers, since you're using a grid anyway.

Advertisement

Are you certain that the image from the website isn't just a lucky accident and would look exactly like yours if it was upside down? If you remove the obstacle, then there are multiple paths through the red region with equal score. And if the heuristic is even slightly optimistic (which is what happens, when you set the weight to 2 on the website), all of them have to be evaluated. It may be due to random/arbitrary shuffling in the open list.

This if statement is never true....


if (OpenList.SingleOrDefault(node => node.Position == Neighbor.Position).G_Vaule + G_Score < CurrentNode.G_Vaule)

This is because the g_score is equal for all "edges" and thus the score of a path is a multiple of the steps taken. With equal amounts of steps, you can only find a shorter path to a node in the open list, if the previous path went along an edge with a higher g_score.

If you don't care for the shortest path, you can use a pessimistic heuristic to reduce the search space though I'm not sure if this introduces any corner cases that have to be handled in the algorithm (like updating nodes in the closed list).

Edit: I misread what you ment by setting the weight to 2. I tried the website and the weight is actually the weight of the heuristic, so setting it to 2 makes the heuristic pessimistic and *not* admissible. However, the algorithm on the website is broken. Setting the weight to 0 should make A* behave like Dijkstra, which it doesn't.

Just to clarify, this is what can happen when the heuristic is (extremely) pessimistic:

[attachment=26575:nonAdmissible.png]

Usually a small search space, but sometimes non optimal solution.


it could just be a difference in heuristics

This. Even assuming that the same heuristics function is used (Euclidean distance?), the difference in results is probably caused by different rounding of values or different floating point precision being used.

Also, does your algorithm have a stop condition when the target has already been found?

I believe the people that bring up floating-point inaccuracies are mistaken. Assuming the nodes have integer coordinates, the particular heuristic function he is using doesn't introduce any rounding errors.

Advertisement

Guys there is no issue with the floating-point. I'm using Vector2 just to store an int position of the grid. When I give the position of the starting point and target point I give it in grid or array coordinates (for example 1, 2, 3, 4, 5 .... 15) I don't use pixel coordinates.

so my starting node is 5, 5 for example and ending node is 10, 10. If I convert that to pixels that would be 5 * 16, 5*16. I'm using 16 because thats the size of each tile. so that will be equal to 80x80px.

So i'm using Vector2 to store int not floating points, even though the vector2 takes a floating point i'm casting it to an int. reason is it cleaner to use a vector2 rather than doing this


int PosX = 5;
int PosY = 5;

//I can just do this
Vector2 Position = new Vector2(5, 5);

I think I figured out what is the problem. I'm not calculating the correct distance from the starting node to the target node. I will try to fix and i will post an update.

I give up. I have been working on this for almost a week and I'm no where close to solving this..... I don't know what to do.....

Go step by step and check what node you think should be explored next, and which one is actually explored next. Pay attention to the values of cost and the heuristic. Debugging is a very useful skill and you shouldn't pass this opportunity to learn it.

Go step by step and check what node you think should be explored next, and which one is actually explored next. Pay attention to the values of cost and the heuristic. Debugging is a very useful skill and you shouldn't pass this opportunity to learn it.

Your right, I will give another shot.

This topic is closed to new replies.

Advertisement