你问:
为什么?- is_fakt(L)
...但是在许多结果 答案之后它挂起。
你说一个数字。这个数字是 62 次按下SPACE才能到达循环的那一刻。不是很长吗?而且你的程序很小。您将如何有机会在更大的计划中做同样的事情?别担心,有帮助。但是你需要从不同的角度来看待这个程序。
在 Prolog 中理解一个具体查询的非常精确的执行几乎是不可能的。你有两种不同类型的控制流交错加上奇怪的数据结构,它们不需要存在,但稍后“进来”;有时。所有这一切都打开了一整套可能的执行痕迹,这些痕迹非常详细,以至于你的大脑会溢出——更糟糕的是:你的大脑仍然会假装你了解一切,但实际上你不了解。并且错误在您的程序中有大量的聚会时间。这些虫子会在未来的某个时间点咬人,但只是在虫子咬人的基础上。这可能非常令人沮丧。毕竟,程序很小,应该很容易理解(按照命令式语言的标准)。但是,对于其他语言中非常复杂的问题,Prolog 程序往往非常紧凑。
尝试使用示踪剂逐步了解我的意思。你会看到各种各样的事情发生。而且大部分都是无关紧要的。
幸运的是,有一些方法可以理解 Prolog,但在这里你必须依赖语言本身的良好属性。对于未终止的本地化原因,最好是开始考虑故障切片。通过将目标添加到程序中,您可以从程序中获得失败片段false
。如果生成的程序仍然没有终止,那么我们有一个原因为什么我们的原始程序也没有终止。
想一想:我们不是试图理解你的程序,而是做一些人类更擅长的事情:做出有根据的猜测。这个猜测可能会出错,但我们可以很容易地检查它。一开始你会很不擅长猜测。很快你就会发现你可以系统地做很多事情。现在变得无关紧要的所有代码都被删除了。
:- 使用模块(库(clpfd))。
事实(处理= A):- 0..1 中的 A。
fact(numYears=B) :- B in 0..sup, false。
fact(numDrugs=C) :- C in 0..sup, false。
事实(处理 2=D):- D 在 0..1,假。
fact(cParam=E) :- E in 0..4, false。
is_differentfact(X,X) :- 假。
is_differentfact(元素=_,其他元素=_):-
差异(元素,其他元素)。
is_fakt([])。
is_fakt([X|Xs]) :-
事实(X),
地图列表(is_differentfact(X),Xs),
is_fakt(Xs)。
我们得到了什么?我们可以更快地缩小问题范围:
?- is_fakt(Xs)。
Xs = [] ;
Xs = [治疗=_G180099],
_G180099 在 0..1 ;
**循环**
在继续之前,我试着理解你的意思is_fakt/1
。您可能的意思是:所有事实都以他们的名字命名,并确保没有重复。现在我们只有名为 的事实treated
,所以我们只能产生一个长度为 1 的列表。然后它循环。
你说:
我不知道为什么 Prolog 不能返回所有可能的值X
。
要挑剔,那是不对的。Prolog 确实列举了所有可能的值X
。但后来它并没有终止。
((要考虑的一些注意事项:您真的想以这种方式获得该列表吗?您将获得所有排列!使用长度为n的列表,您将获得n!不同的答案。对于n = 10,即 3628800。这是,你想要什么?可能不是。))
但让我们首先坚持确定不终止的确切原因。
为了更好地确定原因,让我们“关闭”所有答案。所以我们is_fakt(L),
false
改为查询:
:- 使用模块(库(clpfd))。
事实(处理= A):- 0..1 中的 A。
fact(numYears=B) :- B in 0..sup, false。
fact(numDrugs=C) :- C in 0..sup, false。
事实(处理 2=D):- D 在 0..1,假。
fact(cParam=E) :- E in 0..4, false。
is_differentfact(X,X) :- 假。
is_differentfact(元素=_,其他元素=_):-
差异(元素,其他元素)。
is_fakt([]) :-假。
is_fakt([X|Xs]) :-
事实(X),
maplist(is_differentfact(X),Xs), false ,
is_fakt(Xs)。
那是最小的故障片。因此,它maplist/2
首先不会终止。您的想法是确保X
具有与 中的事实名称不同的事实名称Xs
。但如果Xs
不受约束,那将永远不会终止。让我们尝试一下:
?- maplist(is_differentfact(X),Xs)。
Xs = [] ;
X = (_G496=_G497),
Xs = [_G508=_G509],
差异(_G496,_G508);
X = (_G552=_G553),
Xs = [_G564=_G565, _G570=_G571],
差异(_G552,_G570),
差异(_G552,_G564);
X = (_G608=_G609),
Xs = [_G620=_G621, _G626=_G627, _G632=_G633],
差异(_G608,_G632),
差异(_G608,_G626),
差异(_G608,_G620);
X = (_G664=_G665),
Xs = [_G676=_G677, _G682=_G683, _G688=_G689, _G694=_G695],
差异(_G664,_G694),
差异(_G664,_G688),
差异(_G664,_G682),
差异(_G664,_G676);
X = (_G720=_G721),
Xs = [_G732=_G733, _G738=_G739, _G744=_G745, _G750=_G751, _G756=_G757],
差异(_G720,_G756),
差异(_G720,_G750),
差异(_G720,_G744),
差异(_G720,_G738),
差异(_G720,_G732)...
看起来不太好......但我们可以做得更好:
?- maplist(is_differentfact(X),Xs), false。
**循环**
所以它循环。这就是不终止的原因。为了解决这个问题,我们必须在故障切片的剩余可见部分做一些事情......
有关更多信息,请查找标记为故障切片的其他解释