如何解决如何在Prolog中获得not效果
我正在尝试创建一个递归调用自身的规则,并找到遍历有向图的所有可能路径。我正在使用 findall()
这样做。函数是traverse(Start,End)
。
我有:
traverse(Start,End,[li]) :-
node(Start,End),append(End,Li).
traverse(Start,[Li]) :-
node(Start,Z),traverse(Z,append(Start,Li).
/*here I would like to check that Z is not a member of Li before
I call traverse(Z,I kNow I can check that it is a member
using member(Z,Li) but how to I check it is not a member in
prolog*/
findalltraverses(Start,[list]) :-
findall(_,traverse(Start,End).
解决方法
开始之前:这种语言叫做 prolog。
您的代码有几个不同级别的错误/错误。这是它们的(不完整)列表:
-
findall
需要一个右括号。 -
findall
需要 3 个参数。第一个位置是您感兴趣的内容,第二个是如何选择数据(哪个调用),第三个是您的答案的容器。您对容器感兴趣,因此findalltraverses
应将其作为属性。 - 节点和边之间存在差异。一条边连接两个节点。
- 变量以大写字母或下划线开头。
- 如果变量
L
与列表统一,则您不必像[L]
那样声明它,因为对于示例L=[1,2,3]
[L]
将变为 {{1 }} 是一个列表,其中包含一个包含[[1,3]]
、1
和2
的列表。 - 对于递归调用,您通常有两种情况:结束设置和递归调用设置。你的这个概念是对的。
-
3
有 3 个参数:listsappend
、L1
和L2
,其中L3
和 {{1} } 附加的是L1
。 - 您的谓词
L2
有 3 个属性。没有为 2 个属性定义谓词L3
。 - 您不能覆盖变量。一旦设置了变量的值,就不能再更改它。例如:如果您有一个数字
traverse/3
并且想要增加它,您需要使用不同的变量来保存结果:traverse/2
。 - 将单个元素
N
附加到列表N1 is N+1
作为头元素(意思是将它放在第一个位置)可以通过头尾写法来完成:E
。对于L
和[E|L]
,E=1
变为L=[2,3]
。 - 为了避免无限循环,您需要跟踪您已经访问过的节点。但是,如果您对从
[E|L]
到[1,3]
的路径感兴趣,您需要以某种方式转发该路径。不可能仅将列表与访问过的节点一起使用,因为在通过递归后退时不会保留此知识。所以你的Start
谓词应该有 4 个属性。 - “不”可以用
End
表示,意思是“无法证明”。
好的,这里截取了一个工作代码。递归结束部分有点不同,因为它不检查从 traverse
到 \+
是否存在边,而是询问 Start
和 End
是否相同。如果是,则结果路径仅包含此节点。这很重要,因为在剪切的代码中,路径将在通过递归(Start
)返回时构建,而包含访问节点的列表在进入时会增长递归 (End
)。
[Start|Path]
让我们测试一下!
[Start|Visited]
看起来不错。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。