Prolog - How do I get the tail to not be null

徘徊边缘 提交于 2019-12-10 17:57:33

问题


I have the following problem:

Define a predicate sorted(LL), that is satisfied when the list LL contains other lists that are sorted in order of increasing length. For example:

?- sorted([[],[1],[1,1],[1,1,1]]) -> yes.
?- sorted([[],[1],[1,1]]) -> yes.
?- sorted([[1],[],[1,1],[1,1,1]]) -> no.

And I have this code so far:

% shorter/2

shorter([],_).
shorter([_|T1], [_|T2]) :- shorter(T1,T2).

% sorted/1

sorted([]).
sorted([_]).
sorted([L1,L2 | T]) :- shorter2(L1, L2), sorted([L2,T]).

The problem is contained in the above line: sorted([L2,T]). When only one element is left in the list of lists, that call will append an empty list [] because of which shorter/2 will fail. It is depicted in the following SWIPL trace.

[trace]  ?- sorted([[1],[2,3]]).
   Call: (6) sorted([[1], [2, 3]]) ? creep
   Call: (7) shorter2([1], [2, 3]) ? creep
   Call: (8) shorter2([], [3]) ? creep
   Exit: (8) shorter2([], [3]) ? creep
   Exit: (7) shorter2([1], [2, 3]) ? creep
   Call: (7) sorted([[2, 3], []]) ? creep <-- empty list appended
   Call: (8) shorter2([2, 3], []) ? creep
   Fail: (8) shorter2([2, 3], []) ? creep
   Fail: (7) sorted([[2, 3], []]) ? creep
   Fail: (6) sorted([[1], [2, 3]]) ? creep

回答1:


You have two typos in the last clause of the sorted/1 predicate, which should be:

sorted([L1,L2| T]) :- shorter(L1, L2), sorted([L2| T]).



回答2:


@PauloMoura already gave you the right answer. Is there anything to learn about this? How did you encounter that problem? And how can you locate such problems systematically? I assume that you did not jump into the debugger to look at all those traces for sheer curiosity and a low on supply of animated gifs.

You rather encountered a problem. That is, you had the goal sorted([[1],[2,3]]). which you expected to succeed, but it did not. So you had here some unexpected failure. Sometimes also called insufficiency or incompleteness. This means that the definition for sorted/1 is too specialized, it describes a set of solutions that is too small — at least it misses sorted([[1],[2,3]]).

It often helps to minimize the problem, first. Also sorted([[],[3]]) fails, although we expect it to succeed. And sorted([[],[]]) even loops.

Understanding non-termination

Loops? That's often even easier to localize in a pure Prolog program. I will add goals false and goals like T = [] into the program. The resulting program fragment (called a failure slice) certainly will become completely dysfunctional. But it will retain a very nice property. For: if this new fragment loops, then also the original program will loop. Here is that program that still loops:

?- sorted([[],[]]), false.

sorted([]) :- false.
sorted([_]) :- false.
sorted([L1,L2 | T]) :- T = [], L1 = [], L2 = [],
   shorter(L1, L2),
   sorted([L2,T]).

shorter([],_).
shorter([_|T1], [_|T2]) :- false,
   shorter(T1,T2).

in other words:

sorted([[],[]]) :-
   shorter([],[]),
   sorted([[],[]]).

So, procedurally speaking, that rule does not (always) reduce the length of the list.

Concluding reading

Another way to understand the problem is to read the recursive rule right-to-left in the direction the arrow is pointing. Actually, :- is meant to symbolize ←, well, 1970s style (listen to this French 1972 summerhit to until you understand). So let's try this. I will read:

sorted([L1,L2 | T]) :- shorter2(L1, L2), sorted([L2,T]).
                                         ^^^^^^^^^^^^^^ starting here

I start on the right side and interpret this as:

Provided, sorted([L2,T]) is true.

Maybe some extra remark: Now, you might get pretty uneasy. You might say: Who knows this? Maybe that is not true at all! But the point is, it's just conditional. OK?

and provided shorter(L1, L2) is true


then, we can conclude that sorted([L1, L2|T]) is true.

So we take a list of length 2 as granted and conclude that a list of length 2 or more holds as well.

But where do we actually state that a list of length 2 holds? There is no other place than this rule. Thus: Nowhere is this stated. And thus lists of length 2 or longer will never be sorted.



来源:https://stackoverflow.com/questions/26726484/prolog-how-do-i-get-the-tail-to-not-be-null

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!