基于Korf 1992的c++实现递归最佳优先搜索的问题

Problems implementing recursive best-first search in C++ based on Korf 1992

本文关键字:递归 最佳优先搜索 问题 实现 c++ Korf 1992 基于      更新时间:2023-10-16

我在c++中实现本文中描述的算法时遇到了两个主要问题:正确地终止算法和释放动态分配的内存,而不会出现段错误。

下面是本文提供的伪代码:

RBFS (node: N, value: V, bound: B)
    IF f(N)>B, return f(N)
    IF N is a goal, EXIT algorithm
    IF N has no children, RETURN infinity
    FOR each child Ni of N,
        IF f(N) < V AND f(Ni) < V THEN F[i] := V
        ELSE F[i] := f(Ni)
    sort Ni and F[i] in increasing order of F[i]
    IF only one child, F[2] := infinity
    WHILE (F[1] <= B)
        F[1] := RBFS(N1, F[1], MIN(B, F[2]))
        insert N1 and F[1] in sorted order
    return F[1]

这里,f(Ni)是"计算"的函数值,而f [i]是f(Ni)当前存储的值。

这是我的c++实现,我必须使用一个全局变量来跟踪目标是否已经达到(注意,我试图最大化我的f(n)值,而不是最小化,所以我颠倒了不等式,顺序,最小/最大值等):

bool goal_found = false;
bool state_cmp(FlowState *lhs, FlowState *rhs)
{
    return (lhs->value > rhs->value);
}
int _rbfs(FlowState *state, int value, int bound)
{
    if (state->value < bound) // Returning if the state value is less than bound
    {
        int value = state->value;
        delete state;
        return value;
    }
    if (state->is_goal()) // Check if the goal has been reached
    {
        cout << "Solved the puzzle!" << endl;
        goal_found = true; // Modify the global variable to exit the recursion
        return state->value;
    }
    vector<FlowState*> children = state->children();
    if (children.empty())
    {
        //delete state; // Deleting this state seems to result in a corrupted state elsewhere
        return INT_MIN;
    }
    int n = 0; // Count the number of children
    for (const auto& child: children)
    {
        if (state->value < value && child->value < value)
            child->value = value;
        else
            child->update_value(); // Equivalent of setting stored value to static value (F[i] := f(Ni))
        ++n;
    }
    sort(children.begin(), children.end(), state_cmp);
    while (children.front()->value >= bound && !goal_found) 
    {// Loop depends on the global goal_found variable since this is where the recursive calls happen
        if (children.size() < 2)
            children.front()->set_value(_rbfs(children.front(), children.front()->value, bound));
        else
            children.front()->set_value(_rbfs(children.front(), children.front()->value, max(children[1]->value, bound)));
    }
    // Free children except the front
    int i;
    for (i = 1; i < n; ++i)
        delete children[i];
    state->child = children.front(); // Records the path
    return state->child->value;
}
void rbfs(FlowState* initial_state)
{
    // This is the actual function I invoke to call the algorithm
    _rbfs(initial_state, initial_state->get_value(), INT_MIN);
    print_path(initial_state);
}

我的主要问题是:

  1. 是否有一种方法来终止这个函数,而不是使用一个全局变量(bool goal_reached)没有一个完整的重新实现?递归算法通常有一些基本情况来终止函数,但我没有看到一个明显的方法来这样做。
  2. 我似乎不能删除死胡同状态(当状态没有孩子)没有运行到分段错误,但不删除它导致未释放的内存(每个状态对象是动态分配)。如何修改这段代码以确保释放了经过它的所有状态?

我用gdb运行了这个程序,看看发生了什么,似乎在删除死角状态之后,下一个递归调用的状态实际上不是NULL,而是似乎被损坏了。它有一个地址,但它包含的数据都是垃圾。不删除那个节点可以让程序很好地终止,但是很多状态没有得到释放。此外,我最初使用的是经典的、迭代的最佳优先搜索(但是对于我来说,它占用了太多的内存,而且速度要慢得多),在这种情况下,所有动态分配的状态都被适当地释放了,所以问题就在这段代码的某个地方(是的,在调用rbfs之后,我在main()中释放了路径上的每个状态)。

在您的代码中,有

children.front()->set_value(_rbfs(children.front(), ...

其中state_rbfs里面,因此是children.front()

在_rbfs中,有时会删除state。因此,可以删除children.front(),然后用->set_value调用。这就是你的问题。

你调用delete有什么原因吗?