[英]SWI-prolog : how to make a circular list by using some facts
loop1(a).
loop1(b).
loop1(c).
loop1(d).
circular(d, a).
circular(b, c).
circular(b, d).
circular(a, b).
所以当我打电话:
in_cycle(a, Cycle).
它会返回:
[a,b,d,a]
如果我打电话给:
in_cycle(b, Cycle).
它会返回:
[b,d,a,b].
但是,如果您致电:
in_cycle(c, Cycle).
它会返回:
false. (because no loop is included).
这是我的尝试:
in_cycle(C,Cycle) :- circular(C,Cycle1),in_cycle(Cycle1,Cycle).
我知道此谓词有一个非常严重的问题:它不会停止...我真的想知道我应该添加哪种基本情况,以便该谓词停止? 我应该添加一个条件,以便当序言找到相同的字母时,序言将停止吗?
如果有人可以帮助我,将不胜感激!
- - - -更新 - - - -
check([Y,_|Z]) :- check([Y|Z]).
in_cycle(C, [C]).
in_cycle(C, [C, C1|Cycle]) :- circular(C, C1),check([C,C1|Cycle]),
in_cycle(C1, [C1|Cycle]).
circular(a, a).
被循环[a]
? 知道最短的周期是什么,可以帮助您找到谓词的完成条件(其中之一)。 in_cycle/2
永远不会提及任何列表。 您需要使用[Head | Tail]
[Head | Tail]
构造在其中某处,以便能够将元素添加到列表中。 in_cycle(Current_symbol, Cycle, Start_symbol)
。 然后,您可以从in_cycle/2
调用它。 让我们看看您的尝试:
in_cycle(C, Cycle) :-
circular(C, Cycle1),
in_cycle(Cycle1, Cycle).
您可以在提示符处使用trace
命令查看正在发生的情况: trace, in_cycle(a, X).
按空格键单步执行程序。 按h寻求帮助,按a退出。 使用notrace.
再次退出跟踪模式。
在逐步执行此过程时,您会发现谓词很好地循环了整个循环,但是X
永远不会成为列表。 那很糟。
让我们尝试建立一个清单。 正如我在第(3)点中提到的那样,您已经对列表有所了解。 列表的第一个元素与in_cycle
的第一个参数in_cycle
。 更重要的是,列表的第二个元素与您在circular/2
可以找到的元素相同。 因此,我们知道一个循环至少包含两个元素。 这个怎么样?
in_cycle(First, [First, Next|Cycle]) :-
circular(First, Next),
in_cycle(Next, [Next|Cycle]).
如果您现在跟踪它,您会发现X
发生了一些事情,但实际上仍然没有任何有用的东西。 Cycle
仍然是一个谜,我们只是在不断地了解事实。 您在这里需要一些结束条件。 让我们尝试一个简单的方法:
in_cycle(First, [First]).
in_cycle(First, [First, Next|Cycle]) :-
circular(First, Next),
in_cycle(Next, [Next|Cycle]).
哇! in_cycle(a, X)
突然给出结果! 似乎所有使用以a
开头的circular
连接的列表。 那不是我们想要的,但是也许我们正在接近?
一个问题是in_cycle(Next, [Next|Cycle])
实际上不正确!
如果执行in_cycle(a, X)
,您已经知道X
应该成为[a, b, d, a]
,因此将这些值填充到in_cycle(First, [First, Next|Cycle])
,您将获得:
First = a
Next = b
Cycle = [d, a]
当您进入in_cycle(Next, [Next|Cycle])
,这意味着它是in_cycle(b, [b, d, a])
。 但是[b, d, a]
不是一个循环! 您需要能够以某种方式区分这两种情况。 一种方法是调用一个单独的谓词,如我在(4)中提到的那样,以跟踪您的起始元素是什么。
如果您可以找到返回该节点的路径,则该节点处于循环中。 使用path/4
:
in_cycle(C, [C|Cs]) :-
circular(C, A),
path(circular, Cs, A,C).
现在,该谓词是否终止? 我们如何系统地测试呢? 我们如何确保我们不会忘记任何特殊情况? 对于像这样的纯单调程序,终止测试是微不足道的1 :只需接受最通用的查询 ! 那是:
?- in_cycle(C, Cs).
C = d,
Cs = "dabd" % [d,a,b,d]
; C = b,
Cs = "bdab"
; C = a, Cs = "abda"
; false. % it terminates!
(请参阅此答案,如何获得"bdab"
代替[b,d,a,b]
)。
Prolog的优点是上述查询构成了终止证明 。 您可以构成的每个查询都包含在上述查询中。 并且由于更一般的查询已经终止,因此任何更具体的查询也将终止! 任何!
所有这一切,甚至对于circular/2
任何可变自由事实都成立。 但是,这种证明不能像针对特定事实的证明那样容易地进行。
1请注意, 琐碎的意思是属于琐事 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.