DCG和左递归

2023-12-20

我正在尝试实现一个 dcg,它采用一组 {a,b,c,d}* 形式的字符串。我遇到的问题是,如果我有一个 s([a,c,b], []),它返回 true,这是正确的答案,但是当我有 s([a,c,f],[]) 形式的查询时,它不会返回答案,并且会耗尽本地堆栈。

s --> [].
s --> s,num.
num --> [a].
num--> [b].
num--> [c].
num--> [d].

Use phrase/2

咱们试试吧phrase(s,[a,b,c])代替s([a,b,c],[])。原因很简单:通过这种方式,我们清楚地表明我们正在使用 DCG(dcg /questions/tagged/dcg) 而不是普通的谓词。phrase/2是语法的“官方”界面。

所以你的第一个问题是为什么phrase(s,[a,c,f])不终止,同时phrase(s,[a,b,c])“给出正确的答案”——正如你所说。现在,很快就能回答:both不要终止!但phrase(s,[a,b,c])找到解决方案/答案。

通用端接

These are two things to distinguish: If you enter a query and you get an answer like true or X = a; you might be interested to get more. Usually you do this by entering SPACE or ;ENTER at the toplevel. A query thus might start looping only after the first or several answers are found. This gets pretty confusing over time: Should you always remember that this predicate might produce an answer ; another predicate produces two and only later will loop?

The easiest way out is to establish the notion of universal termination which is the most robust notion here. A Goal terminates iff Goal, false terminates. This false goal corresponds to hitting SPACE indefinitely ; up to the moment when the entire query fails.

所以现在尝试:



?- phrase(s,[a,c,f]), false.
   loops.
  

但是也:



?- phrase(s,[a,b,c]), false.
   loops.
  

从通用终止的角度来看,两个查询都不会终止。在最常用的词中,终止相当于通用终止。找到答案或解决方案就是这样,但不是终止。因此,只要您对答案感到满意,有些查询看起来就无害,但本质上不会终止。但很高兴您这么快就发现了这一点:如果您仅在正在运行的应用程序中发现这一点,那就更糟糕了。

查明原因

下一步让我们确定不终止的原因。您可以尝试使用调试器或跟踪器,但很可能它根本不会给您一个很好的解释。但有一个更简单的方法:使用故障切片 /questions/tagged/failure-slice。只需添加非终结符{false}进入你的语法;和目标false到谓词中。我们可以在这里利用一个非常美丽的财产:

If失败切片不会终止then原程序不会终止。

因此,如果我们很幸运并且找到了这样的切片,那么我们可以确定只有当剩余的可见部分发生更改时才会发生终止somehow。最有帮助的切片是:



?- phrase(s,[a,b,c]), false

s --> [], {false}.
s --> s, {false}, num.
  

你的程序已经所剩无几了!走了是num//0!没人关心num//0。这意味着:num//0可以描述anything,无论如何——程序仍然会循环。

为了解决这个问题,我们必须改变可见部分的一些东西。所剩无几了!正如您已经观察到的,我们这里有一个左递归。修复它的经典方法是:

重新制定语法

您可以轻松地将语法重新表述为正确的递归:



s --> [].
s --> num, s.
  

现在两个查询都终止。这是编译器构造中也已知的经典方法。

但在某些情况下,重新表述语法是不合适的。这个简单的例子不是这种类型,但它经常发生在具有某种故意歧义的语法中。在这种情况下,您仍然可以:

添加终止诱导参数



?- Xs = [a,b,c], phrase(s(Xs,[]), Xs).

s(Xs,Xs) --> [].
s([_|Xs0],Xs) --> s(Xs0,Xs1), num, {Xs1=Xs}.
  

本质上不终止的查询

无论您做什么,请记住并非每个查询都可以终止。如果你问:“告诉我所有存在的自然数——实际上是所有的自然数,一一的!”那么回答这个问题的唯一方法就是从 0 开始,然后将它们数起来。因此存在疑问,其中存在无限的答案/解决方案,我们不能责怪可怜的 Prolog 试图实现我们的愿望。然而,在这种情况下我们最喜欢的是以公平的方式枚举所有解决方案。我们可以通过具有良好终止属性的语法来做到这一点;也就是说,以固定长度列表结尾的语法。就像这样:



?- length(Xs, M), phrase(s, Xs).
  

有关如何应用失败切片的其他示例,请参阅标签故障切片 /questions/tagged/failure-slice.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DCG和左递归 的相关文章

  • 在 Prolog、尾递归中计算斐波那契数列

    我想在 Prolog 中以递归尾部模式计算斐波那契数列 fibonacci 0 0 fibonacci 1 1 fibonacci N Result fibonacci N 1 0 fibonacci N Result Count Coun
  • Prolog 实现 and/2、or/2、nand/2、nor/2、xor/2 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想在序言中实现以下谓词并将它们用于真值表 and 2 or 2 nand 2 nor 2 xor 2 也许有人可以告诉我如何实现和
  • 转换句子会产生无限循环 - 但如何转换呢?

    我不明白这是哪里出了问题 请注意 我对 Prolog 很陌生 我确信我错过了一些东西 只是不知道那可能是什么 有人可以帮我吗 谢谢 这是我的代码 printSentence printSentence W write W write nl
  • 计算序言中列表的排列

    在 序言艺术 第二版中有一个问题 您应该定义一个谓词 Even permutation Xs Ys 和类似的奇数排列 当您查询时 例如 Even permutation 1 2 3 2 3 1 和 odd permutation 1 2 3
  • 以系统的方式报告 Prolog 中查询失败的“原因”

    我正在 Prolog 中寻找一种方法 模式或内置功能 我可以用它来返回why一组谓词失败 至少就数据库中的谓词而言 当用户在系统中提出查询时 我试图能够说的不仅仅是 那是错误的 例如 假设我有两个谓词 blue 1如果某物是蓝色的 则为真
  • 我应该在 Prolog 和一般情况下避免尾递归吗?

    我正在阅读 立即学习 Prolog 在线书籍 以获取乐趣 我正在尝试编写一个谓词 该谓词遍历列表的每个成员并向其添加一个 使用累加器 我已经在没有尾递归的情况下轻松完成了 addone addone X Xs Y Ys Y is X 1 a
  • Prolog 展平列表

    flatten A B R islist A gt flatten A R1 R R1 write A append A R1 R flatten B R1 flatten X X islist 这是我写的代码 但我有奇怪的问题 I get
  • Same_length/2 更好的纯版本

    鉴于频繁的纯定义same length 2 as same length same length As Bs same length As Bs same length L L loops 是否有一个纯粹的定义不会在这种情况下循环 类似于纯
  • SWI-Prolog 中的跨模块“接口”调用

    这可能是 SWI Prolog 模块系统特有的 假设我们有三个 Prolog 模块 在 SWI Prolog 模块系统中 robin 在文件中robin pl arthur 在文件中arthur pl helper 在文件中helper p
  • 使用 prolog 添加另外两次出现

    我有一个清单 a b a a a c c 我需要为每个元素添加两次以上的出现 最终结果应该是这样的 a a a b b b a a a a a c c c c 如果列表中有一个与下一个项目相同的项目 那么它会继续下去 直到出现一个新项目 当
  • 将 SWI Prolog 代码编译为 Windows 可执行文件 - 解析器 Grails3 项目

    我正在尝试构建解析器 Grails3 项目https github com RichardMoot Grail https github com RichardMoot Grail谁的教程是http www labri fr perso m
  • 如何验证涉及 diff/2 约束的交换性?

    围绕 diff 2 约束有很多炒作 特别是作为对 2 和 2 的某些非声明性的救援 这种非声明性通常被描述为非单调性 并给出了非交换性的例子 但是测试涉及 diff 2 的测试用例是否可交换的方法是什么 这是我想要做的元解释 我做了交换性测
  • 如何为这个“移动块”Prolog 练习实现求解谓词?

    我正在使用 Ivan Bratko 的书 人工智能编程 学习 Prolog 我发现实施拟议练习的最后部分有些困难 该练习是一个使用图形来决定如何移动块并按顺序排列它们的程序 这是与程序必须执行的操作相关的图像 正如您在上图中看到的 可以使用
  • 变量的多个值介于 0 和数字序言之间

    所以我一直在尝试自学序言 我认为我进展顺利 然而 我有点坚持我正在尝试的这一种方法 toN N A A 等于 0 到 N 1 之间的整数值 按升序生成 所以 toN 5 A 将是 A 0 A 1 A 2 A 3 A 4 我对序言还很陌生 所
  • Prolog - 通过演绎减少知识库

    我需要创建一个规则来搜索与 my rule 匹配的事实 这些事实将用于改变知识库 my rule Conclusion Premise 我有这个知识库可以开始 dynamic is 2 is m1 house is m1 thing is
  • Prolog 列表列表获取所有元素

    我有一个列表列表 decide 1 2 3 2 3 6 4 K 我想按 返回所有可能的解决方案 规则是首先返回其列表大小为 1 的值 然后我想返回其大小大于1的值 size 0 size Xs L size Xs N L is N 1 he
  • WAM 中的扁平化形式

    WAM 教程重构指出查询 p Z h Z W f W 需要使用以下原则进行扁平化 话虽这么说 查询扁平化形式是 X3 h X2 X5 X4 f X5 X1 p X2 X3 X4 我对外部变量的定义感到困惑 请考虑以下内容 p Z h Y a
  • 如何使用append/3在prolog中递归构建列表?

    我需要了解一些事实的价值 这部分似乎正在发挥作用 fact1 A Val1 fact2 B Val2 A B 但是一旦我尝试附加这些值 Val1 Val2 通过使用append 3谓词到列表 OutList 我只得到一个可能的解决方案 而不
  • Prolog 谓词参数中实例化模式指示符的含义

    查看Prolog文档 谓词签名有时会写成如下 foo Bar Baz Qux Mop 什么是 and 我该如何解释它们 另外 这些是唯一存在的还是还有更多 在这种情况下 这些前缀运算符代表实例化模式 即它们告诉您哪些参数应该是变量或在调用谓
  • Prolog,确定图是否是非循环的

    我需要定义一个谓词 acycling 1 它将一个图作为输入并确定该图是否是非循环的 所以根据我的理解 graph1 a b graph1 b c graph1 c a 将返回 no 和 graph2 a b graph2 b c 将返回是

随机推荐

  • IModelBinder 上的 BindProperty 和 SetProperty 有什么区别

    我正在 Mvc 应用程序中创建自定义模型绑定程序 我想将字符串解析为枚举值并将其分配给模型属性 我已经让它工作了BindProperty方法 但我也注意到有一个SetProperty方法 protected override void Bi
  • PDFBox 按钮执行 javascript 关闭文档

    我的用例是在 pdf 页面上有一个像这样的按钮 实际上是将它们添加到现有页面 但现在我只想看到它对任何东西都有效 Back 它所做的只是关闭当前的 pdf 页面 这个想法是打开多个选项卡 每个选项卡都是一个 pdf 然后当您点击 后退 按钮
  • 从 BigQuery 中的查询返回数组(重复字段)

    我是 BigQuery 和 SQL 的新手 我有一张包含以下详细信息的表格 Schema ID String Nullable BCats String Repeated ID可以重复 Preview ID BCats ABCD BCat2
  • 如何使用美汤进入下一页?

    我必须从网站的 5 个页面中提取信息 每页的末尾都有 下一页 按钮 这是下一个按钮的 html 代码 li class pagination next span class icon arrowright thin pagination b
  • didDiscoverPeripheral“构建失败”错误

    我不确定为什么这段代码无法构建 并且错误消息似乎相当神秘 Code var centralManager CBCentralManager var nrf8001Peripheral CBPeripheral override func v
  • Polymer 1.0:如何在不使用 的情况下将事件传递给子节点元素?

    这个堆栈溢出答案 https stackoverflow com a 32590511 1640892建议使用
  • 调用宏中的其他函数

    如何在宏中调用其他函数 宏 以下似乎不起作用 即使我定义bar with define syntax define bar hello define syntax foo stx syntax case stx a b bar Racket
  • getElementById 其中 Element 在运行时动态创建

    我已经使用innerHTML标签在运行时创建了一个对象 现在我想使用getElementById访问这个元素 当我访问该元素时它返回NULL值 请给我建议任何方向 以便我能够实现这一目标 这是我正在使用的以下代码提示 In HTML div
  • 使用数组设置间隔

    我想使用setInterval函数于jQuery为了每 4 秒创建一个包含一个数组内容的警报 然而 我的警报会在短时间内显示数组的所有值 并且在显示所有值后停止 4 秒 each html5 EDM Coca Cola creativity
  • 使用“hasBackground”进行 Espresso 测试

    如何使用布局背景的颜色进行浓缩咖啡测试 目前使用有背景 https developer android com reference android support test espresso matcher ViewMatchers htm
  • JSON.parse() 不起作用

    我的服务器有一个 json canApprove true hasDisplayed false 我可以像这样解析 json var msg JSON parse canApprove true hasDisplayed false ale
  • 如何在C中定义函数指针数组

    我有一个小问题 我正在尝试动态定义函数指针数组calloc 但我不知道如何写语法 多谢 函数指针的类型就像函数声明一样 但用 代替函数名 所以一个指向 int foo int 将会 int int 为了命名该类型的实例 请将名称放在星号后面
  • 如何从对象的数组记录集中获取嵌套的 HTML 列表?

    我有一个由 SQL 查询返回的对象数组 其中 top id 是我的父 ID 字段 Array 0 gt stdClass Object id gt 1 top id gt 0 name gt Cat 1 1 gt stdClass Obje
  • 如何确定最接近的纵横比

    给定一个矩形形状 S 长宽比为 sx sy 以及另外两个矩形形状 A 长宽比为 ax ay 和 B 长宽比为 bx by 我如何找出形状 A 或 B 中哪一个具有最接近 S 的长宽比 形状的大小并不重要 是 sx sy ax ay 和 sx
  • 获取数据库表中的数据,如果不存在则将其插入,否则返回行 ID

    我有一个包含 date file creation 列的表文件 我想创建一个包含日期文件创建的表日期 当我插入新文件时 我检查表日期是否存在 我返回行 ID 并将其作为外部插入键在表文件中 否则我插入一个新日期并获取其新行 ID 以将其插入
  • 页面中的 Nuxtjs 异步等待在页面刷新时不起作用

    我尝试使用 vuex 和 nuxt js 在页面的 fetch 方法中获取数据 但是每当有人刷新页面时 它都会失败 但当我通过 nuxt 导航导航时 它会工作 所以在我的页面中我有 fetch store params store disp
  • 添加一列排名

    我有一些数据 test lt data frame A c aaabbb aaaabb aaaabb aaaaab bbbaaa 等等 所有元素的长度都相同 并且在我获取它们之前就已经排序了 我需要创建一个新的排名列 第一 第二 第三 之后
  • 删除 R 输出中的反引号

    我有某些变量lm在 R 中自动用反引号 反引号换行 例如名称中带有冒号的变量 经过一些处理后 我尝试用以下方法写出线性模型的变量和系数write table 不幸的是 反引号也被写出来了 如何防止这些反引号被写入 举一个简单但不切实际的例子
  • C# 调用 ActiveDirectory 的 SetPassword 函数的问题

    我成功创建了一个新用户 然后尝试使用以下代码设置其初始密码 newUser AuthenticationType AuthenticationTypes Secure newUser Invoke SetPassword new objec
  • DCG和左递归

    我正在尝试实现一个 dcg 它采用一组 a b c d 形式的字符串 我遇到的问题是 如果我有一个 s a c b 它返回 true 这是正确的答案 但是当我有 s a c f 形式的查询时 它不会返回答案 并且会耗尽本地堆栈 s gt s