最长递增子集Prolog

最长递增子集Prolog,prolog,Prolog,我想在Prolog中创建,以查找输入列表中最长的递增子集。例如,输入[3,1,2]列表,输出为[1,2] ?- subset([3,1,2], X). X = [1,2] 我有代码显示此列表的所有子集: subset([],[]). subset([_|X],Y):-subset(X,Y). subset([A|X],[A|Y]):-subset(X,Y). 有人能帮我找到最长的递增子集吗?你是说[1,3,5,6,7]就是[4,1,3,8,9,5,6,7]的答案吗?你真的是指子集,还是仅仅指

我想在Prolog中创建,以查找输入列表中最长的递增子集。例如,输入[3,1,2]列表,输出为[1,2]

?- subset([3,1,2], X).
X = [1,2]
我有代码显示此列表的所有子集:

subset([],[]).
subset([_|X],Y):-subset(X,Y).
subset([A|X],[A|Y]):-subset(X,Y).

有人能帮我找到最长的递增子集吗?

你是说
[1,3,5,6,7]
就是
[4,1,3,8,9,5,6,7]
的答案吗?你真的是指子集,还是仅仅指子列表,即列表的连续部分

如果是后者,则不需要子集。搜索是线性的。如果在列表
[a,b,c,d,e,f]
中发现
d>e
且递增序列
[a,b,c,d]
停止,则无需立即从
b
重新启动搜索:序列仍将在
d
处中断。您只需从
e
继续搜索即可

因此,在搜索过程中,我们只需携带一些附加信息,即。当前和迄今为止获胜的子序列。以及它们的长度

longest_incr([],0-[]).
longest_incr([A|B],RL-R):-                  % R is the result, of length RL
    longest_aux(B,[],0, [A],1, RL-R). 

longest_aux([],   Win,N, Curr,K, RL-R):- 
    ( K>N -> RL=K, reverse(Curr,R) ; RL=N, reverse(Win,R) ).
longest_aux([A|B],Win,N, Curr,K, RL-R):- Curr = [X|_], L is K,
    ( A>X -> longest_aux(B,Win, N, [A|Curr],L+1,RL-R)    % keep adding
    ; L>N -> longest_aux(B,Curr,K, [A],     1,  RL-R)    % switch the winner
    ;        longest_aux(B,Win, N, [A],     1,  RL-R)    % winner unbeaten 
    ).
如果你真的需要最长的子集。。。这里有一个矛盾。一个集合可以重新排列其元素,因此给定列表的最长子集将是

longset_subset(L,R):- sort(L,S), R=S.
也许你指的是最长的保序子序列,也就是说,它被允许是非连续的。然后,您可以使用
findall
或类似谓词收集
子集
的所有解决方案,并分析这些结果:

longest_subseq(L,R):- 
    findall( S, subset(L,S), X),
    maplist( longest_incr, X, Y),
    keysort( Y, Z), 
    last( Z, _Len-R).
上面有很多冗余。我们可以尝试通过只允许增加子序列来提高其效率:

incr_subseq([],[]).
incr_subseq([_|X],Y):- incr_subseq(X,Y).
incr_subseq([A|X],[A|Y]):- incr_subseq(X,Y), ( Y=[] ; Y=[B|_], A<B).

或者,可以调整线性搜索
最长增量
,以获得更有效的解决方案。它不会只保留一个获胜的子序列,而是在输入列表中保留所有相关的可能性。

你是说
[1,3,5,6,7]
[4,1,3,8,9,5,6,7]
的答案吗?你真的是指子集,还是仅仅指子列表,即列表的连续部分

如果是后者,则不需要子集。搜索是线性的。如果在列表
[a,b,c,d,e,f]
中发现
d>e
且递增序列
[a,b,c,d]
停止,则无需立即从
b
重新启动搜索:序列仍将在
d
处中断。您只需从
e
继续搜索即可

因此,在搜索过程中,我们只需携带一些附加信息,即。当前和迄今为止获胜的子序列。以及它们的长度

longest_incr([],0-[]).
longest_incr([A|B],RL-R):-                  % R is the result, of length RL
    longest_aux(B,[],0, [A],1, RL-R). 

longest_aux([],   Win,N, Curr,K, RL-R):- 
    ( K>N -> RL=K, reverse(Curr,R) ; RL=N, reverse(Win,R) ).
longest_aux([A|B],Win,N, Curr,K, RL-R):- Curr = [X|_], L is K,
    ( A>X -> longest_aux(B,Win, N, [A|Curr],L+1,RL-R)    % keep adding
    ; L>N -> longest_aux(B,Curr,K, [A],     1,  RL-R)    % switch the winner
    ;        longest_aux(B,Win, N, [A],     1,  RL-R)    % winner unbeaten 
    ).
如果你真的需要最长的子集。。。这里有一个矛盾。一个集合可以重新排列其元素,因此给定列表的最长子集将是

longset_subset(L,R):- sort(L,S), R=S.
也许你指的是最长的保序子序列,也就是说,它被允许是非连续的。然后,您可以使用
findall
或类似谓词收集
子集
的所有解决方案,并分析这些结果:

longest_subseq(L,R):- 
    findall( S, subset(L,S), X),
    maplist( longest_incr, X, Y),
    keysort( Y, Z), 
    last( Z, _Len-R).
上面有很多冗余。我们可以尝试通过只允许增加子序列来提高其效率:

incr_subseq([],[]).
incr_subseq([_|X],Y):- incr_subseq(X,Y).
incr_subseq([A|X],[A|Y]):- incr_subseq(X,Y), ( Y=[] ; Y=[B|_], A<B).

或者,可以调整线性搜索
最长增量
,以获得更有效的解决方案。与其只保留一个获胜的子序列,不如在输入列表中保留所有相关的可能性。

只是出于好奇,在prolog中是否可以实现这样的方法来查找最长的递增子序列:

  • 您可以找到列表的所有子集
  • 你会发现,这些子集中有哪些在增加
  • 然后你搜索最长的

如果可能的话,我怎么能在Prolog中做到这一点呢?

出于好奇,在Prolog中有没有可能实现这样的方法来寻找最长的递增子序列:

  • 您可以找到列表的所有子集
  • 你会发现,这些子集中有哪些在增加
  • 然后你搜索最长的

如果可能的话,我怎么能在Prolog中这样做呢?

根据他的
子集
,我实际上假设他指的是“最长的递增子序列”。有很多算法可以做到这一点。在他的例子中,他可以简单地列举所有递增的子序列(他称之为子集),看哪一个是最长的。@Boris你是指连续的还是非连续的?根据他的
子集
,可能是第二个案例?非连续,根据定义。如果它是连续的,我猜它将被称为子字符串。然而,顺序很重要(因此是-序列)。有很多可用的算法。@Boris是的,这似乎是最符合逻辑的。我确实提到了打电话给findall那里…)也许你能给我举个例子,让我学习如何创建最长的谓词?正如我提到的,我仍然在学习PrologI,根据他的
子集
,他实际上会假设他是指“最长的递增子序列”。有很多算法可以做到这一点。在他的例子中,他可以简单地列举所有递增的子序列(他称之为子集),看哪一个是最长的。@Boris你是指连续的还是非连续的?根据他的
子集
,可能是第二个案例?非连续,根据定义。如果它是连续的,我猜它将被称为子字符串。然而,顺序很重要(因此是-序列)。有很多可用的算法。@Boris是的,这似乎是最符合逻辑的。我确实提到了打电话给findall那里…)也许你能给我举个例子,让我学习如何创建最长的谓词?正如我提到的,我仍在学习列表的序言
X
,答案
R
将满足
排序(X,R)
。因为无论元素的顺序如何,集合都被认为是相等的。如果您指的是子序列,即包含原始顺序的元素,可能来自列表中的非连续区域,那么这正是这个问题所要问的。我已经更新了