使用 \==/2 或 diff/2

2023-11-26

如果我想确保两个变量不会实例化为同一个术语,首选的方法是什么?

假设我需要在图中找到有向边,并且节点本身不能有边:

node(a, x, y). node(b, z, x). node(c, y, y).

(这里的边是 a -> c, b -> a,但是notc -> c)

以下作品:

edge(A, B) :- node(A, _, X), node(B, X, _), A \== B.

这也有效[swi-prolog]:

edge(A, B) :- dif(A, B), node(A, _, X), node(B, X, _).

显然这不起作用(因为 A 和 B 都还没有实例化?):

edge(A, B) :- A \== B, node(A, _, X), node(B, X, _).

我想我对第一个解决方案的问题是,使用更复杂的node谓词之前可能会发生很多不必要的统一edge失败了。这dif另一方面是在一个库中,这表明它不适合在如此简单的情况下使用(尽管它具有我似乎正在寻找的确切功能)。


仅出于优雅和说教的原因,dif/2在这里以及在绝大多数其他情况下显然是更可取的,因为正如您已经注意到的那样,否则“可能会发生许多不必要的统一”,而且还因为dif/2是一个纯粹且良好的声明性谓词,可以在子句主体中的所有方向和任何位置使用,而不改变程序的含义,与(\==)/2. dif/2也是 SWI-Prolog 中的自动加载谓词,这意味着您需要not显式导入任何库以使用它,并且dif/2像任何内置谓词一样可用。

如果你使用dif/2您可以更轻松地推理您的代码。例如,在您的情况下,您从以下开始:



edge(A, B) :- node(A, _, X), node(B, X, _), dif(A, B).
  

然后,如你所知dif/2是一个完全纯粹的谓词,你知道你也可以将其写为:



edge(A, B) :- dif(A, B), node(A, _, X), node(B, X, _).
  

此外,既然你知道dif/2总是终止,你知道这个改变最多可以improve程序的终止属性。

像所有的约束一样,dif/2是用来使用的。我强烈推荐它而不是不可交换的不纯谓词。

如果您担心性能,这里有一个小比较,只是比较dif/2反对非声明性(\==)/2在两个谓词可以互换使用的用例中:



?- N = 1_000_000, time((between(1,N,_),dif(a,b),false)).
% 11,000,005 inferences, 0.352 CPU in 0.353 seconds (100% CPU, 31281029 Lips)

?- N = 1_000_000, time((between(1,N,_),a\==b,false)).
%@ % 3,000,001 inferences, 0.107 CPU in 0.107 seconds (99% CPU, 28167437 Lips)
  

因此,使用时有时会带来性能优势(\==)/2。然而,使用这样的低级谓词也有更严重的缺点:它更难理解、更容易出错、并且不是声明性的。

因此我建议简单地使用dif/2来表达两个术语不同。

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

使用 \==/2 或 diff/2 的相关文章

  • Prolog:消除查询中的重复

    我一直在尝试编写一个简单的代码 其行为方式如下 hasCoppiesOf X a b a b a b a b X a b X a b a b X a b a b a b a b And hasCoppiesOf a b a b a b a
  • 编写 Prolog 谓词的最佳实践是什么,以便它以指定参数的不同方式工作

    我正在尝试实现一些简单的谓词 例如 my length 或 my append 如果我们事先知道我们想要找到列表的长度 或者我们想要附加两个列表 这对我来说很容易 即我知道什么是输入 什么是输出 在 Prolog 中 可以用其他方式做事 如
  • Prolog 程序从列表中删除每个第 n 个元素

    您能帮我解决以下问题吗 编写三元谓词delete nth从列表中删除每个第 n 个元素 样本运行 delete nth a b c d e f 2 L L a c e false delete nth a b c d e f 1 L L f
  • Prolog,如何在 write() 中显示多个输出

    go match Mn Fn write Matching Result nl write Mn write match with write Fn match Mn1 Fn1 person may female 25 blue perso
  • 关于构建列表直至满足条件

    我想解决 巨猫军团之谜 https youtu be YeMVoJKn1Tg由 Dan Finkel 使用 Prolog 编写 基本上你从 0 然后使用以下三个操作之一构建此列表 添加5 添加7 或采取sqrt 当您成功建立一个列表后 您就
  • Prolog 变量查询中的“\+”问题

    我正在读 七周七种语言 atm 我对一些 Prolog 查询感到困惑 我不明白对 否 的回答 The friends pl文件看起来像这样 likes wallace cheese likes grommit cheese likes we
  • 寻找最大最小值集合

    我正在尝试编写一个 天真的或半天真的 程序 给定一组元素和许多玩家将其划分为这个数量的玩家 并且对于每个这样的划分取最小值 按总和 子集 然后 我想计算所有这些最小除法的最大值 这被称为https en wikipedia org wiki
  • 如何从序言中的列表中删除列表?

    我想在序言中实现以下问题 Given L1 1 2 3 4 and L2 2 3 4 调用名为remove list L1 L2 L 的函数将从L1中删除L2 所以L将是 1 但是 如果第二个列表的元素与 L1 中的元素顺序不同 或者更准确
  • SWI-Prolog 中的约束编程

    我想要一个包含三个元素 A B 和 C 的列表 L 并具有以下约束 use module library clpfd L A B C L ins 1 3 A B C 但是 它给出了一个错误 Syntax error Operator exp
  • 求解序言中极其简单的方程:A = B + C?

    我有一个非常简单的方程 我希望能够在序言中求解 A B C 我希望能够编写一个谓词来表达这种关系 它可以处理任何一个未实例化的参数 无需推广到更复杂的关系或方程 myEquation A B C something 我可以使用以下语义进行调
  • 如何在 Prolog 中计算数字序列的和

    任务是计算从0到M的自然数之和 我使用SWI Prolog编写了以下代码 my sum From To From gt To my sum From To S From 0 Next is 1 S is 1 my sum Next To S
  • 在列表列表中查找形状

    节目说明 该计划的目的 我的程序旨在计算 20X15 大小的平面中形状的位置 我有一个形状列表 其中包含形状类型 其 ID 半径或高度以及其在平面上的预期 X Y 位置 我有一个不同的二元运算列表 仅包含形状类型 其 id 及其与另一个形状
  • 在 prolog 中读取用户输入的字符串

    我是 Prolog 初学者 我正在使用 swi prolog 刚刚开始使用它 我需要将用户输入字符串拆分到列表中 我尝试了以下代码 但出现错误 指出 在子句正文中完全停止 无法重新定义 2 write Enter the String nl
  • Prolog 罗马数字(属性语法)

    我正在做一项作业prolog questions tagged prolog扫描数字列表并应返回该列表是否是有效的罗马数字以及数字的十进制值 前任 1 roman N I N 1 true 2 当我运行我认为应该工作的程序时 十进制值总是正
  • SWI Prolog 使用的检查优化会发生什么情况?

    去引用SICStus Prolog 手册 https sicstus sics se sicstus docs 3 12 9 html sicstus Occur html 逻辑编程背后的通常数学理论禁止 创建循环项 规定发生检查应该是 每
  • Prolog内存问题

    我想找到一种方法来分析我在序言中编写的谓词 一个巨大的谓词 的内存使用情况 我目前正在运行它swi http www swi prolog org and yap http www dcc fc up pt vsc Yap document
  • Same_length/2 更好的纯版本

    鉴于频繁的纯定义same length 2 as same length same length As Bs same length As Bs same length L L loops 是否有一个纯粹的定义不会在这种情况下循环 类似于纯
  • 通过递归扩展 Prolog 目标?

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

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

    这可能是 SWI Prolog 模块系统特有的 假设我们有三个 Prolog 模块 在 SWI Prolog 模块系统中 robin 在文件中robin pl arthur 在文件中arthur pl helper 在文件中helper p

随机推荐