在Prolog中递归组合列表

时间:2018-01-03 17:22:47

标签: list prolog

我在Prolog中做了这个。

contains(psu,[fan,cable,transformer]).
contains(screen,[panel,cable,psu]).

contains(fan,[plastic,cable,copper]).
contains(cable,[copper,plastic]).
contains(transformer,[wire,core]).
contains(wire,[copper,plastic]).
contains(panel,[glass,polarizingfilter,liquidcrystals]).

我想提出一个问题componentsOf(X),它会在列表中返回X的所有组件和子组件,例如

componentsOf(psu)
[fan,cable,transformer,plastic,copper,wire,core]

我尝试每次都附加一个列表,最后使用sort/2但是没有用。有什么帮助吗?

3 个答案:

答案 0 :(得分:0)

您可以这样使用findall/3

solve(L1,L2,L3):-
    findall(X,contains(X,_),L1),
    findall(X,contains(_,X),L2),
    findall([X,Y],contains(X,Y),L3).

查询:

?- solve(L1,L2,L3).
L1 = [psu, screen, fan, cable, transformer, wire, panel],
L2 = [[fan, cable, transformer], [panel, cable, psu], [plastic, cable, copper], [copper, plastic], [wire, core], [copper, plastic], [glass, polarizingfilter, liquidcrystals]],
L3 = [[psu, [fan, cable, transformer]], [screen, [panel, cable, psu]], [fan, [plastic, cable, copper]], [cable, [copper, plastic]], [transformer, [wire, core]], [wire, [copper, plastic]], [panel, [glass, polarizingfilter, liquidcrystals]]]

L1中,您获得所有组件,在L2中获得所有子组件,在L3中获得包含组件和子组件的列表。

答案 1 :(得分:0)

SWI-Prolog的图书馆 ordset 是您的朋友:

componentsOf(Obj, Components) :-
    components_([Obj], Comps),
    ord_subtract(Comps, [Obj], Components).

components_(Lst, Out) :-
    % change setof with findall because setof fails when L is empty
    findall(X, (member(Y, Lst), contains(Y, X)), L),
    flatten([Lst | L], FlatL),
    list_to_ord_set(FlatL, SetL),
    ord_intersection(Lst, SetL, Intersection, Difference),
    (   Difference = []
        ->  Out = Intersection
    ;   components_(Difference, Out1),
        ord_union(Out1, SetL, Out)).

示例:

 ?- componentsOf(psu, Out).
Out = [cable, copper, core, fan, plastic, transformer, wire].

编辑我用 findall 更改 setof

?- componentsOf(screen, X).
X = [cable, copper, core, fan, glass, liquidcrystals, panel, plastic, polarizingfilter|...].

答案 2 :(得分:0)

Here你可以看到一个有效的解决方案,即固定点迭代的例子。

components(SoFar, Cs) :-
    setof(P, C^L^
        ((member(C,SoFar),contains(C,L),member(P,L))
         ;member(P,SoFar)), Ts),
    ( Ts = SoFar -> Cs = Ts ; components(Ts, Cs) ).

part_components(P, Cs) :-
    % corrected to exclude P from Cs
    % components([P], Cs).
    contains(P, Ps),
    components(Ps, Cs).

紧凑但效率不高...... OTOH,它产生可读(良好,有序)的答案:

?- part_components(screen,R).
R = [cable, copper, core, fan, glass, liquidcrystals, panel, plastic, polarizingfilter, psu, transformer, wire]