prolog置换(?L,?L1)

时间:2014-05-28 15:41:36

标签: prolog permutation

我正在尝试创建一个permute(?L,?L1)谓词。

这样当我执行时:

      permute([1,2], X).
      X = [1,2] ;
      X = [2,1]; 

      permute(X, [1,2]).
      X = [1,2]
      X = [2,1]

如果您运行内置功能:

      permutation(X, [1,2]).

堆栈溢出。

我尝试了以下代码:

permute1([], []).
permute1([X|Rest], L) :-
    permute1(Rest, L1),
    select(X, L, L1).

 permute2([], []).
 permute2(L, [P | P1]) :-
     select(P, L, L1),
     permute2(L1, P1).

 generator(L, L1):-
      findall(X,permutation(L,X),L1).

但没有工作。 我事先感谢你的帮助。

3 个答案:

答案 0 :(得分:2)

permutation/2的问题在于它没有尽可能好地终止。因此,首先,我们需要了解Prolog谓词的终止属性我们可以期待什么。请注意,我们可以在不查看具体定义的情况下进行这些考虑!

解决方案集

首先,开始考虑查询具有哪些解决方案。如果该集合是有限的,则Prolog might终止。如果它是无限的,我们将不得不枚举所有解决方案,那么我们不能指望Prolog终止。在您的示例中,请考虑

  • permute(L,[])。在这里,集合是有限的,因此如果谓词将终止,那将是很好的。

  • permute([X],L)。这里的集合是无限的。

但我们真的对看到所有解决方案感兴趣吗?像X = 1, L = [1]和更多,还有更多?事实上,X可能是任何术语,因此我们可以放松(或概括)我们对Prolog的期望:我们可能会对包含变量的答案替换感到满意,而不是具体的解决方案。 。实际上,L = [X]描述了所有无限多个解决方案,只有一个答案替换。

答案

如果解决方案集是无限的,我们将尝试确定是否可以用有限多个答案来描述该集合。但是,如果只有无限多个答案能够代表解决方案集,则查询不得终止。考虑: permute([a,b|L],[c,d|M]).在这里,我们需要无限多的答案。喜欢 L = [c,d], M = [a,b] ; L = [c,d,X1], M = [a,b,X1]等。如果谓词在这种情况下终止,则会遗漏一些解决方案。

因此,经过这些考虑,我们现在知道谓词可能终止的位置,以及必须循环的位置。在我们的情况下,permute/2必须循环,如果两个参数都是部分列表

如果其中一个列表的长度已知,则将谓词(理想情况下)置于另一个方向上。

请注意,对于permute/2,两个列表的长度相同,因此:

same_length([], []).
same_length([_|Xs], [_|Ys]) :-
   same_length(Xs, Ys).

permute(Xs, Ys) :-
   same_length(Xs, Ys),  % redundant goal
   permutation(Xs, Ys).

您可以使用library(lambda)撰写same_length/2,而不是maplist(\_^_^true,Xs, Ys)

答案 1 :(得分:1)

你可以在permutation附近找一个包装器:

permute(X, L) :-
    ( nonvar(L) ->
        permutation(X, L)
    ;
        permutation(L, X)
    ).

答案 2 :(得分:1)

另一种方法是将列表的长度限制为相同(假设至少有一个列表被实例化):

permute(L, P) :-
    length(L, N),
    length(P, N), !,
    permutation(L, P).