广度首先搜索算法不起作用导致无限循环

发布于 2025-01-29 06:11:46 字数 4664 浏览 4 评论 0 原文

我正在尝试进行BFS搜索,在此时,我在搜索状态空间时动态创建图形的节点。我遵循了这本书,但它不起作用,边境一直在运行,而探索的集合仅处于起始值。请帮忙,我被困在这里4天。仍然是初学者程序员。

问题类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    internal class Problem
    {
        public State start { get; set; }
        public State end { get; set; }

        public string[] action = { "UP", "LEFT", "DOWN", "RIGHT" };

        public Problem(State x, State y)
        {
            start = x;
            end = y;
        }

        public State Result(State s , string a)
        {
            State up;

            if (a == "UP" && s.X - 1 >= 0)
            {
                 up = new State(s.X - 1, s.Y);
               
            }
            else if (a == "LEFT" && s.Y - 1 >= 0)
            {
                up = new State(s.X, s.Y-1);
                
            }
            else if (a == "DOWN" && s.X + 1 <  5)
            {
                up = new State(s.X, s.Y+1);
               
            }
            else if( a == "RIGHT" && s.Y + 1 < 11)
            {
                up = new State(s.X + 1, s.Y);
                
            }
           
            return up;

           
        } 
    
        public bool GoalTest(Node<State> goal)
        {
            if (goal.Data.Equals(end))
            {
                return true;
            }
            return false;
        }
    
    }
}

搜索类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    internal class Search
    {
        public void BFS(Problem p)
        {
            Queue<Node<State>> frontier = new Queue<Node<State>>();
            HashSet<string> explored = new HashSet<string>();
            List<Node<State>> nNodes = new List<Node<State>>();

            Node<State> root = new Node<State>() {Data = p.start,};
            frontier.Enqueue(root);

            while(frontier.Count > 0)
            {
                Node<State> next = frontier.Dequeue();
                if(!explored.Add(next.Data.Data)) continue;
               

                next.Children = new List<Node<State>>();
                foreach(string action in p.action)
                {
                    next.Children.Add(new Node<State>() { Data = p.Result(next.Data, action), Parent = next });
                }

                for(int i = 0; i < next.Children.Count; i++)
                {
                    
                        if (p.GoalTest(next.Children[i]) == true)
                        {
                            //Solution(next.Children[i]);
                            break;
                        }
                        frontier.Enqueue(next.Children[i]);
                    
                }
            }
        }

        public void Solution(Node<State> n)
        {
            while(n.Parent != null)
            {
                Console.WriteLine(n.Parent.Data);
            }
        }
    }
}

节点类别

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    internal class Node<T>
    {
        public T Data { get; set; }
        public Node<T>? Parent { get; set; }
        public List<Node<T>> Children { get; set; }

    }
}

状态类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    internal class State
    {
        public int X { get; set; }
        public int Y { get; set; }
        public string Data { get; }

        public State(int x, int y)
        {
            X = x;
            Y = y;
            Data = $"{X}-{Y}";
        }
    }
}

主要程序

using Test;

State start = new State(0, 1);
State end = new State(3, 7);

Problem p = new Problem(start, end);

Search s = new Search();
s.BFS(p);

这实际上是我的作业因此我将其命名为测试。
我正在尝试从这里实现伪代码:(第82页)

更新
它现在不陷入困境,但在循环运行后不会将任何内容输入到控制台中,它应该通过“ parent property” 在目标节点和开始节点之间获得链接。

I am trying to do a BFS search where I dynamically create the Nodes of the graph as I search the State Space. I followed the book but it does not work the frontier keeps on running and the explored set stays at the start value only. Please help, I have been stuck here for 4 days. Still a beginner programmer.

Problem Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    internal class Problem
    {
        public State start { get; set; }
        public State end { get; set; }

        public string[] action = { "UP", "LEFT", "DOWN", "RIGHT" };

        public Problem(State x, State y)
        {
            start = x;
            end = y;
        }

        public State Result(State s , string a)
        {
            State up;

            if (a == "UP" && s.X - 1 >= 0)
            {
                 up = new State(s.X - 1, s.Y);
               
            }
            else if (a == "LEFT" && s.Y - 1 >= 0)
            {
                up = new State(s.X, s.Y-1);
                
            }
            else if (a == "DOWN" && s.X + 1 <  5)
            {
                up = new State(s.X, s.Y+1);
               
            }
            else if( a == "RIGHT" && s.Y + 1 < 11)
            {
                up = new State(s.X + 1, s.Y);
                
            }
           
            return up;

           
        } 
    
        public bool GoalTest(Node<State> goal)
        {
            if (goal.Data.Equals(end))
            {
                return true;
            }
            return false;
        }
    
    }
}

Search Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    internal class Search
    {
        public void BFS(Problem p)
        {
            Queue<Node<State>> frontier = new Queue<Node<State>>();
            HashSet<string> explored = new HashSet<string>();
            List<Node<State>> nNodes = new List<Node<State>>();

            Node<State> root = new Node<State>() {Data = p.start,};
            frontier.Enqueue(root);

            while(frontier.Count > 0)
            {
                Node<State> next = frontier.Dequeue();
                if(!explored.Add(next.Data.Data)) continue;
               

                next.Children = new List<Node<State>>();
                foreach(string action in p.action)
                {
                    next.Children.Add(new Node<State>() { Data = p.Result(next.Data, action), Parent = next });
                }

                for(int i = 0; i < next.Children.Count; i++)
                {
                    
                        if (p.GoalTest(next.Children[i]) == true)
                        {
                            //Solution(next.Children[i]);
                            break;
                        }
                        frontier.Enqueue(next.Children[i]);
                    
                }
            }
        }

        public void Solution(Node<State> n)
        {
            while(n.Parent != null)
            {
                Console.WriteLine(n.Parent.Data);
            }
        }
    }
}

Node Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    internal class Node<T>
    {
        public T Data { get; set; }
        public Node<T>? Parent { get; set; }
        public List<Node<T>> Children { get; set; }

    }
}

State Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    internal class State
    {
        public int X { get; set; }
        public int Y { get; set; }
        public string Data { get; }

        public State(int x, int y)
        {
            X = x;
            Y = y;
            Data = 
quot;{X}-{Y}";
        }
    }
}

Main Program

using Test;

State start = new State(0, 1);
State end = new State(3, 7);

Problem p = new Problem(start, end);

Search s = new Search();
s.BFS(p);

This is actually for my assignment hence I named it test.
I am trying to implement the pseudocode from here: (Page 82)
https://zoo.cs.yale.edu/classes/cs470/materials/aima2010.pdf

Update
It does not stuck now but it does not input anything into the console after the loop runs it is supposed to get the links between the goal node and the start node via the "Parent property".

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

GRAY°灰色天空 2025-02-05 06:11:46

您永远不会检查是否已经探索了节点,因此您可能会输入无限循环:

explored.Add(next.Data.Data);

应该是

if(!explored.Add(next.Data.Data)) continue;

,但代码可能还有其他问题。我强烈建议您阅读Eric Lipperts文章如何调试由于这样的问题应该很容易找到并在调试器的帮助下进行修复。学习如何使用调试器是一项宝贵的技能,它将使故障排除更加容易。

我还建议删除您程序中的所有字符串。相反,您应该创建代表坐标的类型,即一个点或vector2int。我建议将其变为可读的结构,并添加 toString Overload, iqeality&lt; point&gt; 实现,加法扣除,平等的运算符。代表国家并代表偏移。对于各种不同的项目,这种类型都可以重复使用。

You are never checking if nodes are already explored, so you will likely enter an infinite loop:

explored.Add(next.Data.Data);

should be

if(!explored.Add(next.Data.Data)) continue;

But there might be other problems with the code. I would highly recommend reading Eric Lipperts article How to debug small programs since problems like this should be fairly easy to find and fix yourself with the help of a debugger. Learning how to use a debugger is an invaluable skill that will make troubleshooting much easier.

I would also recommend removing all the strings from your program. Instead you should create type representing a coordinate, i.e. a Point, or vector2Int. I would recommend making this a readonly struct, and add ToString overload, IEquality<Point> implementation, operators for addition subtraction, equality etc. This type could then be used both for representing the state, and to represent the offsets. Such a type would be reusable for all kinds of different projects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文