代码之家  ›  专栏  ›  技术社区  ›  Toto

具有扩张状态对象的c a*算法

  •  0
  • Toto  · 技术社区  · 6 年前

    为了解决以下问题,我正在尝试实现a*算法:

    1. 我有一个初始状态
    2. 我可以申请“行动”从一个州到另一个州
    3. 我想用最少的行动达到最后的状态
    4. 对给定状态应用操作很简单(=快速)
    5. 整个状态是一个复杂的对象(内存大,克隆速度慢)

    这个问题来自5/点。

    事实上,当从当前状态中寻找可能的子级时,我不能每次都创建一个全新的状态,因为这样做代价太大(无论是在内存还是速度方面)。因此,我使用的是一个单独的状态,当将操作应用于前一个状态时,我会对其进行变异以反映结果状态。(我可以回滚操作)。我想用下面的方法实现a*

        //_state; //represent the "singleton" states that I can apply and rollback actions instead of cloning it
        while (openNodes.Any())
        {
            var currentNode = openNodes.DeQueue();
            currentNode.AdvanceFromStart(_state); //make _state such as all action on the path from the root to currentNode are played
    
            if (IsFinal(_state))
                return;
    
            AddToVisitedStates(_state);
            foreach(var transition in currentNode.GetPossibleActions())
            {
                var childNode = new Node(initialState:_state,action:transition.Action);
                //here _state is still reflecting the situation from the currentNode point of view
                childNode.ApplyAction(_state);
                //now _state reflect the situation from childNode point of view
                if (WasVisited(_state))
                {
                    childNode.RollbackAction(_state);                
                    continue;
                }
    
                if (childNode.CostToReachNode == 0 ||
                    currentNode.CostToReachNode + transition.Cost < childNode.CostToReachNode)
                {
                    childNode.CostToReachNode = node.CostToReachNode + transition.CostToReachNode;
                    childNode.CostToReachFinal = childNode.CostToReachNode + HeuristicToReachFinalFromState(_state);
                    openNodes.ReOrder(childNode);
                }
                if (!openNodes.Contains(childNode))
                    openNodes.Add(childNode);
    
                childNode.RollbackAction(_state);
            }
            currentNode.RollbackToInitialState(_state);//make _state as initially setup
        }
    

    我不喜欢这个解决方案。A*算法中有没有我遗漏的有用的东西?我还没有完成实现,你看到一些新的问题/一些需要提出的问题了吗?

    也许a*不是正确的算法,我愿意接受任何不同的结果。

    PD:如果相关的话,这是一个C实现

    1 回复  |  直到 6 年前
        1
  •  0
  •   mcdowella    6 年前

    通过在每个对象中存储,而不是存储状态,而是从导致它的初始状态开始的决策序列,可以使它看起来更像普通的a*。当你想处理一个状态时,看看导致当前状态的决策序列,备份到你需要去的状态的共同祖先,然后记录下这组决策。这种变化的代价至多是某个常数因子乘以决策树的深度。如果这是严重的分支和平衡,它可能没有那么深。

    另一个选择是 https://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search 或者有限的差异搜索,使用迄今为止找到的最佳答案(从以前的迭代)和a*启发式来避免可能导致可能的答案的节点。当您完成一个过程时(修剪后),当前对差异或深度的限制实际上并没有阻止您调查想要的每个节点,您知道您已经找到了最佳答案。