path(X, Y, N)
,如果且仅当从节点X
到节点Y
存在长度为N
的路径时返回true。给定的是带有相应权重的有向边列表,例如edge(a, b, 3)
和edge(c, d, 10)
。给定问题非常直接(只需一些递归和基本情况)。但是,我想或许可以进一步扩展。考虑到简单的有向图输入可能包含循环,并且仅包含非负权重,给定节点
A
和B
,请问唯一最短路径的长度是多少。(通过唯一,我是指如果从A
到B
存在多个最短路径,则此谓词应返回false)。下面是一个包含循环的数据库示例(a,b,c,e,a)。
edge(a, b, 1).
edge(b, c, 2).
edge(c, d, 1).
edge(b, d, 4).
edge(c, e, 1).
edge(e, a, 10).
edge(e, d, 6).
我认为为了满足“unique”条件,应该增强原始的
path/3
谓词,将路径信息作为列表包含在其中(以便稍后比较路径唯一性)。这个新的增强体现在新的path/4
谓词中。path(X, X, 0, []).
path(X, Y, N, [Y]) :- edge(X, Y, N).
path(X, Y, N, [Z|T]) :- edge(X, Z, N1), N2 is N - N1, N2 > 0, path(Z, Y, N2, T).
path(X, Y, N) :- path(X, Y, N, _).
根据此代码,我已经发现了一个问题:如果我尝试将谓词与
path(a, b, N, Z)
统一,则无法成功,因为N
无法与N2 is N - N1
统一。但是,如果我将此部分更改为N is N1 + N2
,这仍然不起作用,因为N2
仍未被统一。如果我将整个谓词行更改为:path(X, Y, N, [Z|T]) :- edge(X, Z, N1), path(Z, Y, N2, T), N is N1 + N2.
这将永无止境地运行,因为路径的数量可能是无限的,因为图可能包含循环(我想保持它作为一个挑战)。
至于
shortestpath/3
谓词,我不能找到所有路径并检查所有路径是否更长,因为路径的数量可能由于有一个循环而是无限的。相反,我尝试找到任何长度介于0和给定的 N
之间的路径;如果不存在路径,则这绝对是最短的路径。countdown(N, N).
countdown(N, X) :- N1 is N - 1, N1 >= 0, countdown(N1, X).
shortestpath(A, B, N) :- path(A, B, N), \+((countdown(N, N1), N > N1, path(A, B, N1))).
然而,这并没有解决作为变量给出的N(因为倒计时函数不起作用),更不用说唯一约束了。
所以我的问题是,有没有办法使这个问题可行,或者说它实际上是不可能做到的?如果有这样的解决方案,请在这里提供(或者如果您认为这是一个“作业”问题,请至少指导我正确的方向)。
限制条件:
- 我不想使用任何内置谓词。只能使用“简单”或“核心”谓词,例如\+、is、+等。var、nonvar、asserta和类似的谓词也可以接受(因为没有实现相同功能的替代方法)。 - 我希望它尽可能通用;也就是说,谓词的任何参数都应该能够给出变量。(或者至少有shortestpath/3的最后一个参数,即最短路径的长度,是一个变量)。
我已经查看了以下问题,但它们都没有回答我的情况:
在Prolog中找到两个节点之间的最短路径(不涉及加权边,并且使用复杂谓词(例如
path/4
)。搜索图形的所有路径和最短路径- Prolog(不涉及循环图)。
在图形中找到两个节点之间的最短路径(Prolog),并将结果显示为数组(不涉及加权边)。
请随意指向任何其他解答我的问题的问题。