Prolog 单圈置换
让我们看一个数{1,2,3,4}的排列,其中只有一个圈。例如,它可以是:(2,3,4,1)。我想知道,如何使用Prolog生成所有这样的排列 我知道如何使用Prolog 单圈置换,prolog,permutation,Prolog,Permutation,让我们看一个数{1,2,3,4}的排列,其中只有一个圈。例如,它可以是:(2,3,4,1)。我想知道,如何使用Prolog生成所有这样的排列 我知道如何使用select生成所有排列 但是我想不出如何只生成一个循环(即单循环)置换 有人能给我一点提示或建议吗?你能不能用这个函数来生成所有排列,并过滤掉那些不是“单周期排列”的排列?(由于我根本不清楚什么是‘单周期排列’,恐怕我无法帮助编写该过滤器。) cycle/5谓词构建与您传递的第一个参数对应的循环。第二个参数是一个累加器,初始化为[First
select
生成所有排列
但是我想不出如何只生成一个循环(即单循环)置换
有人能给我一点提示或建议吗?你能不能用这个函数来生成所有排列,并过滤掉那些不是“单周期排列”的排列?(由于我根本不清楚什么是‘单周期排列’,恐怕我无法帮助编写该过滤器。)
cycle/5
谓词构建与您传递的第一个参数对应的循环。第二个参数是一个累加器,初始化为[FirstArgument]
,第三个和第四个参数是原始的列表
和置换
,最后一个参数是结果(包含循环元素的列表)
对的调用对应于/4
检索替代排列中第一个参数的项:
corresponds(Current, List, Permutation, R),
如果这个项目在我们正在构建的周期中,这意味着我们已经完成了周期的构建,所以我们统一了周期
和累加器(Acc
)
如果没有,我们继续使用找到的相应项递归调用谓词,并将其添加到累加器中,以便我们的构建周期现在保存它:
; cycle(R, [R|Acc], List, Permutation, Cycle)).
corresponds(N, [N|_], [R|_], R) :-
!.
corresponds(N, [_|L], [_|P], R) :-
corresponds(N, L, P, R).
用法:
?- one-cycle([1, 2, 3, 4], P).
P = [2, 3, 4, 1] ;
P = [3, 1, 4, 2] ;
P = [3, 4, 2, 1] ;
P = [2, 4, 1, 3] ;
P = [4, 1, 2, 3] ;
P = [4, 3, 1, 2] ;
false.
我的评论意在暗示直接生成单循环置换,而不是生成所有置换并过滤掉由单循环组成的置换 我们或许应该澄清,排列的两种表示法经常被使用。xyz写道“我知道如何生成所有置换”,大概意思是类似于我给出的代码。在这里,所有的排列都是按照列表在一些“标准顺序”列表中重新排列项目的方式来表示的 很明显,有N!各种排列。其中有多少是单圈排列?这个问题很容易通过考虑另一种对排列有用的形式来回答,即作为不相交循环的产物。我们需要区分循环(1,2,3,4)和单位置换[1,2,3,4]。事实上,循环(1,2,3,4)将1映射到2,2映射到3,3映射到4,4映射回1,因此它在列表表示中不是身份置换[2,3,4,1] 现在一个循环循环回到自身,所以我们选择循环符号的起始位置是任意的。例如,如果我们从1开始,那么周期由以下N-1项的顺序决定。这表明有(N-1)!形成一个循环的N个事物的排列(长度必须为N)。因此,我们可以很容易地生成循环形式的所有单循环置换,然后问题就归结为从该循环形式转换为置换的列表形式。[请注意,Mog在另一个方向解决了转换问题:给定一个置换as列表,找出该置换中包含的一个循环(并查看它是否为全长)。] 这是我用来生成给定“标准顺序”列表的所有单周期列表排列的代码,
oneCycle(Identity,Permuted)
:
多亏了在中的讨论,我才能够理解这一切 似乎解决方案很简单,用排列替换输入列表的尾部,形成循环描述,然后将每个元素与其下一个元素进行配对,并对第一个组件进行排序,从而将第二个组件的列表作为结果列表,从而将其转换为列表表示:
单循环置换([A | B],R):-
置换(B,P),
循环对(A,A,P,CP),
排序(CP、SCP),
映射列表(成对,SCP,R)。
成对(X-Y,X,Y)。
循环u对(A,X,[Y|Z],[X-Y|W]):-
循环_对(A,Y,Z,W)。
循环对(A,X,[],[X-A])。
为了更容易地查看循环,只需删除单循环排列中的最后一个目标即可:
单循环对([A | B],SCP):-
置换(B,P),
循环对(A,A,P,CP),
排序(CP、SCP)。
测试:
21?-forall(单循环对([1,2,3,4],SCP),
(映射列表(成对,SCP,Ur),写入((SCP,R)),nl))。
[1-2,2-3,3-4,4-1],[2,3,4,1]
[1-2,2-4,3-1,4-3],[2,4,1,3]
[1-3,2-4,3-2,4-1],[3,4,2,1]
[1-3,2-1,3-4,4-2],[3,1,4,2]
[1-4,2-3,3-1,4-2],[4,3,1,2]
[1-4,2-1,3-2,4-3],[4,1,2,3]
对。
另见:
( member(R, Acc)
-> Cycle = Acc
; cycle(R, [R|Acc], List, Permutation, Cycle)).
corresponds(N, [N|_], [R|_], R) :-
!.
corresponds(N, [_|L], [_|P], R) :-
corresponds(N, L, P, R).
?- one-cycle([1, 2, 3, 4], P).
P = [2, 3, 4, 1] ;
P = [3, 1, 4, 2] ;
P = [3, 4, 2, 1] ;
P = [2, 4, 1, 3] ;
P = [4, 1, 2, 3] ;
P = [4, 3, 1, 2] ;
false.
oneCycle([H|T],P) :-
permute(T,S),
oneCycle2permute([H|S],[H|T],P).
permute([ ],[ ]) :- !.
permute(L,[H|T]) :-
omit(H,L,Z),
permute(Z,T).
omit(H,[H|T],T).
omit(X,[H|T],[H|Z]) :-
omit(X,T,Z).
oneCycle2permute(_,[ ],[ ]) :- !.
oneCycle2permute(C,[I|Is],[P|Ps]) :-
mapCycle(C,I,P),
oneCycle2permute(C,Is,Ps).
mapCycle([X],X,X) :- !.
mapCycle([H|T],X,Y) :-
mapCycleAux(H,T,X,Y).
mapCycleAux(Y,[X],X,Y) :- !.
mapCycleAux(X,[Y|_],X,Y) :- !.
mapCycleAux(_,[X,Y|_],X,Y) :- !.
mapCycleAux(H,[_|T],X,Y) :-
mapCycleAux(H,T,X,Y).