转换句子会产生无限循环 - 但如何转换呢?

2024-05-02

我不明白这是哪里出了问题。请注意,我对 Prolog 很陌生,我确信我错过了一些东西 - 只是不知道那可能是什么。有人可以帮我吗?

谢谢,这是我的代码:

printSentence([]).   
printSentence([W|[]]) :-
    write(W),
    write('.'),
    nl.  
printSentence([W|R]) :-
    write(W),
    write(' '),
    printSentence(R).

transform([], Result).  
transform([Word|Rest], Result) :-
    replace(Word, Replacement),
    append(Result, Replacement, NewResult),
    transform(Rest, NewResult).

replace(my, your).
replace(i, you).
replace(you, me).
replace(am, are).
replace(Word, Word).

test :-
    X = [you, are, my, only, hope],
    transform(X, Result),
    printSentence(Result).

@Junuxx'的回答是解决问题的第一步;您的程序中还存在另一个问题。但首先退后一步:@Junuxx 发现了问题并修复了它。好的。但怎样才能you发现这样的问题吗?其实你问的是»无限循环——但是如何?«

Prolog 的一个很酷的地方是,您通常可以将循环程序定位到程序的一个非常小的片段。这样的片段称为故障切片 /questions/tagged/failure-slice。那就是:阅读冗长的程序不再让人眼花缭乱!

让我们回到你的程序。如果加载它,您将收到如下消息:



Warning: /usager/SO/paranoid.pl:13:
    Singleton variables: [Result]
  

这已经给了你一些很可能是错误的提示。唉,这是not您目前最关心的问题。你最大的问题是目标test loops!

本地化非终止

那么如何才能轻松地了解实际循环的内容呢?

One way就是启动一个跟踪器,它将逐步向您展示 Prolog 如何执行该程序。但是,跟踪器会向您显示许多不相关的细节。细节,在 Prolog 中编程时不需要理解。细节,充满了你的大脑,这样你很可能会完全错过实际的问题。因此,除非您想花时间在充满闪烁线条的屏幕上,否则请远离示踪剂。

另一种方法就是添加目标false到你的程序中。请记住,您的程序已经循环,因此这些额外的目标不会对您造成太大伤害。为什么要用这些破坏你的程序false您一开始就不想写的目标?正是因为这些false目标将通过隐藏“不相关”部分来帮助您检测程序中不终止的罪魁祸首。之所以如此,得益于以下观察:

If失败切片(=您被破坏的程序)不会终止then原始程序也不会终止。

从某种意义上说,失败切片是程序无法终止的一个原因。或者更强烈地说:只要你不改变 failure-slice 中的可见部分;也就是说,只要您只是通过修改故障切片中不可见的部分来碰碰运气,问题就会持续存在!有保证!这不是最好的保证,但总比盲目要好。

这是我得到的失败切片。我删除了printSentence/1因为它不再在片段中使用。我添加了定义append/3。一些 Prolog 提供append/3作为您无法修改的内置谓词。在这种情况下,请使用另一个名称,例如local_append/3– 只是不要忘记替换所有出现的地方!


append([], Zs, Zs) :- false.
append([X|Xs], Ys, [X|Zs]) :-
   append(Xs, Ys, Zs), false.

transform([], Result) :- false.
transform([Word|Rest], Result) :-
    replace(Word, Replacement),
    append(Result, Replacement, NewResult), false,
    transform(Rest, NewResult).

replace(my, your) :- false.
replace(i, you) :- false.
replace(you, me).
replace(am, are) :- false.
replace(Word, Word) :- false.

test :-
    X = [you, are, my, only, hope],
    transform(X, Result), false,
    printSentence(Result).
  

当我加载这个失败切片时,我得到:



?- test.
ERROR: Out of local stack
  

这很好地表明该程序不会终止。在我有限的硬件上,它会耗尽所有资源。 ((说得迂腐一点,这个程序可能仍然会终止,它可能只需要太多的资源。但是请记住:我们有这个if故障切片循环,then整个程序循环。无论如何,证明故障切片的非终止通常会更容易,因为片段更短))。

一些观察:最初,transform/2曾经是递归的。现在,它不再是了。剩下的唯一递归是在append/3。所以我首先看目标append(Result, Replacement, NewResult)我试图找出变量可能是什么。最简单的是第三个参数:NewResult是我们片段中唯一出现的,因此我们可以将其替换为_。第二个参数的变量Replacement一直会me。第一个论点(我现在要看看test/0) 将是一个未实例化的变量。所以我们必须考虑目标append(_, me, _).

只需运行append(_, me, _), false看到这个目标不会终止!您也可以通过检查失败切片来看到这一点。再说一遍:


append([], Zs, Zs) :- false.
append([X|Xs], Ys, [X|Zs]) :-
   append(Xs, Ys, Zs), false.
  

Look at Ys:没人关心,只是“交给”而已。只有第一个和第三个参数可能保证终止!

更多内容请见标签故障切片 /questions/tagged/failure-slice.


印刷精美

Certain restrictions apply! Void where prohibited! You can do above reasoning only with a pure, monotonic Prolog program. Actually, some benign side-effects as the ones you have in your program are OK too. As long as they do not affect the control-flow.


另一个问题

您的程序还有另一个问题。跑步printSentence([you]), false看见了!回溯和副作用不会轻易聚集在一起。对于初学者来说,最好的是避免副作用。看这个问题 https://stackoverflow.com/q/9744641/772868 and 那个答案 https://stackoverflow.com/a/9791028/772868例如,如何消除编程问题中无用的副作用。 为什么不打电话transform([you, are, my, only hope], Xs) or maplist(replace,[you, are, my only, hope], Xs)直接地?它可以让您再次专注于相关部分!

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

转换句子会产生无限循环 - 但如何转换呢? 的相关文章

  • 执行树元解释

    我有根据我之前的问题制作的跟踪元解释器here https stackoverflow com questions 27235148 implementing cut in tracing meta interpreter prolog 我
  • 如何在 Prolog 中为变量(如字符串)分配多个值?

    今天早些时候 我寻求帮助以在序言中构建数据库以及如何通过参数搜索 有人提出了这个 您还可以向每个处理器添加术语列表 例如 processor pentium g4400 brand intel family pentium series g
  • Prolog 同构图

    这里尝试解决同构图问题 作业信息 判断2个无向图是否同构 没有孤立的顶点 顶点数小于30 图的边作为谓词给出 即 e 1 2 f 1 2 我正在尝试使用以下方法 对于每对边 即图 1 和图 2 中的每条边 Try to bind the v
  • 为什么在具体化中将 clpfd 变量分配给实际值?

    我正在开发一个 SWI Prolog 程序 该程序使用 CLP FD 约束来找到特定问题的解决方案 为此 我碰巧需要两个列表的 未定位 重叠 那是 List La长度为A List Lb长度为 B A gt B 未定位的重叠列表是La Lb
  • 在列表列表中查找形状

    节目说明 该计划的目的 我的程序旨在计算 20X15 大小的平面中形状的位置 我有一个形状列表 其中包含形状类型 其 ID 半径或高度以及其在平面上的预期 X Y 位置 我有一个不同的二元运算列表 仅包含形状类型 其 id 及其与另一个形状
  • 导入 csv 文件数据以填充 Prolog 知识库

    我有一个 csv 文件example csv其中包含两列 标题为 var1 和 var2 我想填充一个最初为空的 Prolog 知识库文件import pl具有重复的事实 而每一行example csv处理方式相同 fact A1 A2 f
  • 问题 - 序言中的形式语言

    我正在尝试构建一个 DCG 它可以识别与此形式匹配的所有列表 a n b 2m c 2m d n 我写下了以下规则 s gt s gt ad ad gt a ad d ad gt bc bc gt b b bc c c bc gt a gt
  • SWI Prolog 使用的检查优化会发生什么情况?

    去引用SICStus Prolog 手册 https sicstus sics se sicstus docs 3 12 9 html sicstus Occur html 逻辑编程背后的通常数学理论禁止 创建循环项 规定发生检查应该是 每
  • Prolog 过滤自定义目标失败的所有元素的列表

    我正在尝试写一个谓词filter List PredName Result 过滤一个List目标的所有要素PredName失败并随后返回Result列表 谓词PredName 1应该在调用过程时定义filter 3例如可以是 test N
  • 我应该在 Prolog 和一般情况下避免尾递归吗?

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

    我有一组事实 likes john mary likes mary robert likes robert kate likes alan george likes alan mary likes george mary likes har
  • 通过递归扩展 Prolog 目标?

    我 最终 实现了一些目标 这些目标将根据开始由 开始之后 and duration 然而 计划目标仅接受规定数量的任务 我想扩展计划目标的功能以接受单个列表并在计划时迭代该列表 不幸的是 我认为这将需要与can run and 冲突目标如下
  • 查找相邻成员

    我必须找出列表中的两个成员是否相邻 限制是使用append 3谓词 到目前为止 我已经完成了下面的操作 如果它是真的 它就有效 否则我得不到答案 就像它永远运行一样 adjacent X Y L append L1 X Y T1 appen
  • Prolog中计算数字是否为素数

    我正在尝试计算输入是否是素数 但出了问题 这是我的代码 primeNumber X prime prime A 1 prime prime A B R is A mod B R 1 R A prime prime X B B lt A Ne
  • 将 SWI Prolog 代码编译为 Windows 可执行文件 - 解析器 Grails3 项目

    我正在尝试构建解析器 Grails3 项目https github com RichardMoot Grail https github com RichardMoot Grail谁的教程是http www labri fr perso m
  • 高阶“解决方案”谓词

    我正在使用一个更高阶的 Prolog 变体 它缺少findall 还有一个关于实现我们自己的问题findall here 获取 Prolog 中的解决方案列表 https stackoverflow com questions 419103
  • Prolog:如何在不重复的情况下创建所有可能的组合

    我正在尝试创建一个谓词来查找所有可能的组合而不重复相同的数字 我尝试使用排列谓词 但它发现了重复的列表 例如 permutation 0 1 1 L L 0 1 1 L 0 1 1 L 1 0 1 L 1 1 0 L 1 0 1 L 1 1
  • 判断第一个字母是否是元音序言

    我习惯了过程式编程语言 而且我在 prolog 上遇到了一些困难 缺乏在线资源也是一个遗憾 获取给定变量的第一个字符并检查它是否是元音的最 序言 方式是什么 我想 这样的东西就是我所追求的 这都是伪代码 但这是你解决问题的方法吗 isVow
  • 查找列表中的最大值 - Prolog

    我刚刚接触 Prolog 并尝试编写一个谓词来查找整数列表的最大值 我需要写一个从头开始比较的内容 另一个从最后开始比较的内容 到目前为止 我有 max2 R max2 X Xs R X gt R max2 Xs X max2 X Xs R
  • json 获取 prolog 谓词

    我试图在序言中创建这个谓词 谓词json get 3可以定义为 json get JSON obj Fields Result 这是正确的 当Result可以通过以下方式恢复 中的字段链Fields 列表 从JSON obj 一个字段 代表

随机推荐