星号搜索不打印路线

时间:2014-11-08 21:34:31

标签: java search a-star

我试图实现伪造的A *搜索:

http://web.mit.edu/eranki/www/tutorials/search/

虽然搜索终止并找到目标,但我的print route()方法

> private void printRoute() {
        MyNode i = this.getGoalNode();
        while (i != this.getStartNode()) {

            System.out.println(i.getId());
            i = i.getParent();

        }
    }

陷入了打印循环:

8
7
8
7
8
7
8
7
8
7

我正在解析Open Street地图数据来进行搜索,但我已经验证了我的解析正在使用成功的BFS和DFS。这是我制作的简化模型,用于表示简单的网格。我在从节点1到节点12搜索: 1 2 3 4

5 6 7 8

9 10 11 12

所以1扩展为2和5等

搜索完成时关闭的设置如下所示:

在设置父级时,我的逻辑中必定存在缺陷,但我无法看到它。真的很感激任何帮助。

感谢, MJB

完整的A *代码

import java.util.ArrayList;
import java.util.LinkedList;

public class AStar extends Search {

    private LinkedList<MyNode> openList; // This is basically our frontier
    private ArrayList<MyNode> closedList;// This is the visited set.

    public AStar(MyNode startNode, MyNode goalNode, Parser p) {
        super(startNode, goalNode, p);
        openList = new LinkedList<MyNode>();
        closedList = new ArrayList<MyNode>();

    }

    public void Search() {
        openList.add(this.getStartNode());
        while (!openList.isEmpty()) {
            MyNode q = openList.get(0);

            // find the node with the lowest heuristic value
            for (MyNode node : openList) {
                if (node.getF() < q.getF())
                    q = node;
            }
            openList.remove(q);
            ArrayList<MyNode> successors = q.getSuccessors();
            for (MyNode node : successors) {
                node.setParent(q);
                if (isGoal(node)) {
                    System.out.println("search completed- goal found");
                    printRoute();

                    System.exit(0);
                }
                double g = node.getG()
                        + Search.distFrom(q.getLat(), q.getLon(),
                                node.getLat(), node.getLon());
                double h = Search.distFrom(this.getGoalNode().getLat(), this
                        .getGoalNode().getLon(), q.getLat(), q.getLon());

                node.setF(g + h);

                if (openList.contains(node)) {
                    int openIndex = openList.indexOf(node);

                    if (openList.get(openIndex).getF() < node.getF()) {
                        // do nothing.
                    }
                }
                if (closedList.contains(node)) {
                    int closedIndex = closedList.indexOf(node);

                    if (closedList.get(closedIndex).getF() < node.getF()) {
                        // do nothing.
                    }
                } else {
                    openList.add(node);
                }

            }
            closedList.add(q);
        }

    }

    // checks the goal and returns a boolean.
    private Boolean isGoal(MyNode node) {
        boolean toReturn = false;
        if (node.equals(this.getGoalNode())) {
            toReturn = true;

        }
        return toReturn;
    }

    private void printRoute() {
        MyNode i = this.getGoalNode();
        while (i != this.getStartNode()) {

            System.out.println(i.getId());
            i = i.getParent();

        }
    }

}

编辑:实现了下面的更改(谢谢),但仍然遇到陷入循环的相同问题。还尝试将printRoute()的条件更改为while(i.getParent()!= null),但再次收到相同的错误。

1 个答案:

答案 0 :(得分:0)

您似乎没有错误地实施节点分数。节点的分数应等于:路径从开始到此节点的长度+ 估计路径长度到结束。当你实现它时:估计路径长度从开始到此节点+ 估计路径长度从此节点到完成。

要正确实现算法,您需要存储用于从起始节点获取的路径的长度。所以不要这样:

double g = node.getG() + Search.distFrom(q.getLat(), q.getLon(),node.getLat(), node.getLon());
double h = Search.distFrom(this.getGoalNode().getLat(), this.getGoalNode().getLon(), q.getLat(), q.getLon());    
node.setF(g + h);

你需要这样的东西:

node.setPathLen(q.getPathLen() + dist(q, node)); // set actual length of an actual path from start to this node
double g = node.getPathLen();
double h = Search.distFrom(this.getGoalNode().getLat(), this.getGoalNode().getLon(), q.getLat(), q.getLon());
node.setF(g + h); // save estimation of a path to a goal node

其中dist() - 是附近节点之间的实际距离(在您的情况下为1)

请参阅正确的代码here

也很少有建议:

  1. 使用openList的优先级队列而不是通常的列表

  2. 使用哈希映射存储访问过的笔记(实施中的closeList)