如何改善A-Star算法的性能?

时间:2019-06-04 12:47:15

标签: java algorithm graph-algorithm a-star

我已经实现了A-Star算法,但没有达到预期的性能,如何改善算法的性能。

下面是在while循环中调用的主要功能,直到到达目标节点为止。这是AStar单向实现。

public void step(boolean useQueueOnly) {
        count ++;
        m_fixedNodeId = m_nextNodeId;
        m_fixedCost = m_nextCost;
        int fromNodeId = m_current.getPrevNodeId();

        int arcId = m_network.getFirstArc(m_fixedNodeId);
        while (arcId != Integer.MIN_VALUE) {
            int nextNodeId = m_network.getBegNodeId(arcId);
            if (nextNodeId == m_fixedNodeId) {
                nextNodeId = m_network.getEndNodeId(arcId);
            }
            int arcCost;
            if (m_forwardDirection) {
                arcCost = m_network.getCost(arcId, m_fixedNodeId, fromNodeId);
            } else {
                arcCost = m_network.getCost(arcId, nextNodeId, fromNodeId);
            }

            arcCost = Math.max(MIN_COST_ALLOWED, arcCost);

            if (arcCost != Integer.MAX_VALUE) {
                int newNodeCost = (int) Math.min((long) m_fixedCost + arcCost,
                        Integer.MAX_VALUE);

                int nodePrevCost  = fromMap.get(nextNodeId) != null ? fromMap.get(nextNodeId).getCost() : Integer.MAX_VALUE;

                double approxCost = newNodeCost + m_approximator.approximate(nextNodeId);

                AStarEntry ase = new AStarEntry(nextNodeId, approxCost, arcId, m_current, m_fixedNodeId, newNodeCost);

                if ((nodePrevCost == Integer.MAX_VALUE) &&
                        (newNodeCost != Integer.MAX_VALUE)) {
                    //haven't yet reached this node.
                    if(fromMap.get(nextNodeId) == null){
                        fromMap.put(nextNodeId, ase);
                        m_priorityNodeQueue.add(ase);
                    }

                } else if (newNodeCost < nodePrevCost) {
                    //already reached this node.
                    m_priorityNodeQueue.remove(ase);

                }
            }
            arcId = m_network.getNextArc(m_fixedNodeId, arcId);
        }

        m_current = m_priorityNodeQueue.poll();
        m_nextNodeId = m_current.getNodeId();
        m_nextCost = m_current.getCost();

}

这是我在优先级队列中使用的类。

class AStarEntry implements Cloneable, Comparable<AStarEntry>{

    public double m_weight;
    public int m_nodeId;
    public int m_arcId;
    public int m_prevNodeId;
    public int m_cost;

    public AStarEntry m_parent;

    public AStarEntry(int nodeId, double weight, int arcId, AStarEntry parent, int prevNodeId, int cost) {
        m_nodeId = nodeId;
        m_weight = weight;
        m_arcId = arcId;
        m_parent = parent;
        m_prevNodeId = prevNodeId;
        m_cost = cost;
    }

    @Override
    public int compareTo(AStarEntry o) {

        // assumption no NaN and no -0        
        return m_weight > o.m_weight ? +1 : m_weight < o.m_weight ? -1 : 0;
    }

    public double getWeight() {
        return m_weight;
    }

    public int getNodeId() {
        return m_nodeId;
    }

    public int getArcId() {
        return m_arcId;
    }

    public AStarEntry getParent() {
        return m_parent;
    }

    public int getPrevNodeId() {
        return m_prevNodeId;
    }

    public int getCost() {
        return m_cost;
    }

    @Override
    public String toString() {

        return m_nodeId + " (" + m_arcId + ") weight: " + m_weight;
    }
}

我无法找出性能不佳的原因,请帮助我找出一个原因。

1 个答案:

答案 0 :(得分:1)

在找到解决方案之前,您应该检查探索了多少个节点。

接下来,您可以尝试提高剩余路径成本的过高估计功能(启发式),以减少探索节点的数量。

通常,A *算法的性能主要取决于您使用的启发式方法,而并不是真正的代码优化方法。因此,请尝试将尽可能多的领域知识纳入您的启发式方法,以减少探索节点的数量。