伯克利人工智能课程 - 没有迷宫距离的吃豆人食物启发式?

问题描述

我正在参加与伯克利的 AI 课程类似的课程,我正在尝试为 Q7 找到 foodHeuristic(可以找到问题 here),但是我不允许使用 mazedistance 作为它的实现使用 BFS,扩展节点。 我根本不知道如何找到这种启发式方法。我试过 - 曼哈顿到壁橱食物的距离,曼哈顿到最远食物的距离,添加到剩余食物中的任何一个,曼哈顿到最远食物的距离+曼哈顿从最远食物到其壁橱食物的距离..

实际上到处都有食物的媒体搜索,那么它怎么可能被有效地计算?

甚至可以在没有 mazedistance 的情况下击败 7000 吗?

有关于 foodHeuristic 的任何线索吗?

解决方法

简介

好的,所以这不是一个完整的答案,因为我还没有实现它,所以我不知道它的表现如何。但是,我的方法基于以下几点:

  1. 注释“请确保在处理问题 7 之前完成问题 4,因为问题 7 建立在您对问题 4 的回答之上。”。因此,以曼哈顿距离为一致启发式的 A* 搜索是我们的基础。
  2. “如果您的启发式方法不一致,您将不会获得任何信用”这一事实。

所以他们肯定会引导我们使用比曼哈顿距离更聪明的一致启发式进行 A* 搜索。

检查您的(有时不一致的)启发式

您的前两个启发式:“曼哈顿到壁橱食物的距离”和“曼哈顿到最远食物的距离”绝对是一致的。

您的第三个启发式“添加到剩余食物中的任何一个”与第一个启发式一致,但不是第二个(例如,如果直线走到最远的食物会吃光所有食物,那么您将高估成本)。

您最后的启发式(“曼哈顿距离最远食物+曼哈顿距离从最远食物到其壁橱食物的距离”)也不一致,原因相同:同样,图片直线走到最后一个颗粒导致吃掉所有食物剩下的食物。

因此,到目前为止,您最好的一致启发式方法是“到壁橱食物的曼哈顿距离”+(食物颗粒的总数)- 1。我想知道:您必须使用此启发式方法扩展多少个节点?

更严格的启发式

因此,当我试图找到一致的启发式方法时,我通常会做您所做的:从基本计算开始,然后添加缺失的因素同时保持一致。因此,例如,您的第一个启发式适用于一个颗粒,但不适用于多个。添加剩余食物颗粒的数量使其更紧密,而不会失去一致性。

让我们找出这种启发式方法有效和无效的情况。如果我想象一个方块(没有墙),那么这个启发式方法非常好:我首先到达墙的最近部分,然后我一次吞下一个颗粒(自从我进入后没有浪费任何动作)一个圆圈)。如果它是一条单一的颗粒路径而不是一个正方形,那么我可能会大大低估(例如,最近的点是中间路径;朝一个方向进食需要返回),但我没有看到一种简单的建模方法这个。

回到广场,如果我每隔一个颗粒就删除一次怎么办?估计会减半,但实际上成本是一样的!因此,我们缺少一个重要因素:连接组件的数量

无论您如何进食,您都必须始终从一个连接的组件移动到另一个组件(例如,想象多个断开的路径;我们吃掉一个,然后前往下一个,吞下那个并重复)。

所以我推荐的第一个启发式如下:

  1. 计算食物颗粒的连通分量数 = C。(这个值可以随着你穿过迷宫而逐渐更新。每当你吃掉一个颗粒时,你可能会吃完一个分量,所以 C' = C - 1,或者你可以将一个组件分成多个组件,因此 C' = C + 1 或 C' = C + 2 或 C' = C + 3;只需从您当前位置的 4 个邻居中进行洪水填充即可)。
  2. 使用一致的启发式 (C - 1) + (F - 1) + 曼哈顿距离到最近的颗粒,其中 C 是组件的数量,F 是食物颗粒的数量。

这显然比您现有的启发式方法更严格。主要想法是捕捉颗粒之间的间隙。

更严格的启发式

现在连接的组件之间可能会有很大的间隙(例如,只保留正方形中的每个第 N 个颗粒)。知道我们将访问组件的顺序太复杂了,但是,除了最后访问的组件,我们至少必须前往最近的邻居组件。

所以假设 TravelCost(C_i) 是从颗粒连接组件 C_i 到其最近的相邻连接组件(例如 C_j)的曼哈顿距离。那么 TotalTravelCost 将是 sum(i=1..n)(TravelCost(C_i) - 1) - max(TravelCost(C_i) - 1,i=1..n)。注意两点:

  1. 为了保持一致,我们必须假设最大差旅成本是被跳过的那个,并且
  2. TravelCost(C_i) >= 2 根据定义,所以 TotalTravelCost >= (C-1)。 (如果只剩下一个连通分量,则 TotalTravelCost = C-1 = 0。)

因此,我们更严格的一致启发式将是 TotalTravelCost + (F - 1) + 到最近颗粒的曼哈顿距离。

这实施起来有点麻烦,而且肯定会使每个节点的评估速度变慢,因此我会亲自尝试实施我的第一个建议,并在继续执行此操作之前查看它的执行情况。一些技巧可以使最后的启发式更快:

  • TravelCost(C_i) 不会因为你的最后一步没有吃到颗粒而改变。
  • 当你吃一个小球时,你只需要更新你改变的组件 C_i 的 TravelCost(C_i),以及那些最近的相邻组件是 C_i 的组件。
  • 当您将一个组件拆分为多个组件(即 C' = C + 1 或 C' = C + 2 或 C' = C + 3)时,每个组件的 TravelCost 必须为 2。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...