Prolog - 将二进制函数转换为n-aary函数

时间:2017-02-17 15:38:17

标签: prolog

如果在任一参数上应用相同的函数,我必须在输入中编写一个给出二进制公式(在本例中为ANDs / OR)的谓词,将其转换为n-ary谓词。因此,例如,and(and(A, B), and(C, D))变为and(A, B, C, D)

任何人都可以告诉我如何继续这样做而不告诉我到底要写什么?我想了解如何去做,但我真的觉得很难。我到目前为止只是一个基本案例 - 我不知道它是否正确:

simplify(A, B) :-
    A=..[Name, Arg1, Arg2],
    Name == and, 
    not(compound(Arg1)),
    not(compound(Arg2)),
    B = A.

也就是说,如果我有一个AND并且两个参数都不是复合,那么它意味着简化函数是相同的。我该如何进一步处理?

谢谢!

2 个答案:

答案 0 :(得分:0)

这是我的临时解决方案。它仍然不理想,它变得扁平化了#34;第一个深度级别的函数,所以如果公式中有更深入的其他AND或OR,它就不会到达它们。如何使它工作?

simplify(A, B, Functor) :-  A=..[Name, Arg1, Arg2], Name == Functor, 
                            not(compound(Arg1)), not(compound(Arg2)), B = A.
simplify(A, B, Functor) :-  A=..[Name, Arg1, Arg2], Name == Functor, 
                            Arg1=..[Name|_], Arg2=..[Name|_],
                            simplify(Arg1, C, Functor), simplify(Arg2, D, Functor),
                            C=..[_|ArgsC], D=..[_|ArgsD],
                            append(ArgsC, ArgsD, ArgsB),
                            B =.. [Functor|ArgsB].
simplify(A, B, Functor) :-  A=..[Name, Arg1, Arg2], Name == Functor, 
                            Arg1=..[Name|_],
                            simplify(Arg1, C, Functor),
                            C=..[_|ArgsC],
                            append(ArgsC, [Arg2], ArgsB),
                            B =.. [Functor|ArgsB].
simplify(A, B, Functor) :-  A=..[Name, Arg1, Arg2], Name == Functor, 
                            Arg2=..[Name|_],
                            simplify(Arg2, C, Functor),
                            C=..[_|ArgsC],
                            append([Arg1], ArgsC, ArgsB),
                            B =.. [Functor|ArgsB].

编辑:这个解决方案应该有效(不完整,我仍在编写每个案例)。如果您将公式视为二叉树结构,它会将具有相同键(AND或OR)的每个节点展平为一个,同时保持具有不同键的分隔节点(不要将AND参数与OR混合)。但是,它非常冗长,因为我为每个场景编写了一个案例(例如,[Arg1 is not a compound, Arg2 is an AND][Arg1 is not a compound, Arg2 is an OR]等等,但我不知道是否你可以更优雅地做到这一点。如果可能,请告诉我!

% Case X(a, b) => X(a, b)
simplify(A, B) :-   A=..[Name, Arg1, Arg2], subset([Name], [or, and]), 
                            not(compound(Arg1)), not(compound(Arg2)), B = A, !.

% Case X(X(a, b), c) => X(a, b, c)
simplify(A, B) :-   A=..[Name, Arg1, Arg2], subset([Name], [or, and]), 
                            Arg1=..[Name|_], not(compound(Arg2)),
                            simplify(Arg1, C), C=..[_|ArgsC], 
                            append(ArgsC, [Arg2], ArgsB),
                            B =.. [Name|ArgsB], !.

% Case X(a, X(b, c)) => X(a, b, c)
simplify(A, B) :-   A=..[Name, Arg1, Arg2], subset([Name], [or, and]), 
                            not(compound(Arg1)), Arg2=..[Name|_], 
                            simplify(Arg2, C), C=..[_|ArgsC],
                            append([Arg1], ArgsC, ArgsB),
                            B =.. [Name|ArgsB], !.

% Case X(X(a, b), X(c, d)) => X(a, b, c, d)
simplify(A, B) :-   A=..[Name, Arg1, Arg2], subset([Name], [or, and]), 
                            Arg1=..[Name|_], Arg2=..[Name|_],
                            simplify(Arg1, C), simplify(Arg2, D),
                            C=..[_|ArgsC], D=..[_|ArgsD],
                            append(ArgsC, ArgsD, ArgsB),
                            B =.. [Name|ArgsB], !.

% Case X(X(a, b), Y(b, c)) => X(a, b, Y(b, c))              
simplify(A, B) :-   A=..[Name, Arg1, Arg2], subset([Name], [or, and]), 
                            Arg1=..[Name|_], Arg2=..[DifferentName|_], Name \== DifferentName,
                            simplify(Arg1, C), 
                            subset([DifferentName], [or, and]), simplify(Arg2, D),
                            C=..[_|ArgsC],
                            append(ArgsC, [D], ArgsB),
                            B =.. [Name|ArgsB], !.

% Case X(Y(a, b), X(c, d)) => X(Y(a, b), c, d)
simplify(A, B) :-   A=..[Name, Arg1, Arg2], subset([Name], [or, and]), 
                            Arg1=..[DifferentName|_], Arg2=..[Name|_], 
                            simplify(Arg2, C),
                            subset([DifferentName], [or, and]), simplify(Arg1, D),
                            C=..[_|ArgsC],
                            append([D], ArgsC, ArgsB),
                            B =.. [Name|ArgsB], !.

% Case X(Y(a, b), Y(c, d)) => X(Y(a, b, c, d))
simplify(A, B) :-   A=..[Name, Arg1, Arg2], subset([Name], [or, and]), 
                            Arg1=..[DifferentName|_], Arg2=..[DifferentName|_],
                            simplify(Arg1, C), simplify(Arg2, D),
                            C=..[_|ArgsC], D=..[_|ArgsD],
                            append(ArgsC, ArgsD, ArgsB),
                            E =..[DifferentName|ArgsB],
                            B =.. [Name|[E]], !.

答案 1 :(得分:0)

对于更通用的解决方案(SWI-Prolog),我们可以开始定义两个辅助谓词:

% term_to_list(+Term, -List): convert a Term to a nested List

term_to_list(Term, List) :-
    (   compound(Term)
    ->  compound_name_arguments(Term, Name, Arguments),
        maplist(term_to_list, Arguments, Sublists),
        List = [Name|Sublists]
    ;   List = Term ).

% list_to_term(+List, -Term): convert a nested List to a Term

list_to_term(List, Term) :-
    (   compound(List)
    ->  List = [Name|Sublists],
        maplist(list_to_term, Sublists, Arguments),
        compound_name_arguments(Term, Name, Arguments)
    ;   Term = List).

这些谓词的作用如下:

?- term_to_list(and(and(A,B),or(and(C,D),or(E,F))), List).
List = [and,[and,A,B],[or,[and,C,D],[or,E,F]]].

?- list_to_term([and,[and,A,B],[or,[and,C,D],[or,E,F]]], Term).
Term = and(and(A,B),or(and(C,D),or(E,F))).

在将术语转换为相应的嵌套列表后,我们在被简化的表达式中使用了二元和 n 元布尔函数的统一表示。因此,可以通过以下谓词进行简化:

% simplify(+Expression, -Simplified): convert Expression into a Simplified one

simplify(Expression, Simplified) :-
    term_to_list(Expression, List),
    recursive_simplify(none, List, [NewList]),
    list_to_term(NewList, Simplified).

recursive_simplify(OuterOperator, Term, Simplified) :-
    (   compound(Term)
    ->  Term = [InnerOperator|Arguments],
        maplist(recursive_simplify(InnerOperator), Arguments, NewArguments),
        (   OuterOperator \= InnerOperator
        ->  append([[InnerOperator]|NewArguments], List),
            Simplified = [List]
        ;   append(NewArguments, Simplified) )
    ;   Simplified = [Term]).

以下是一些示例:

?- simplify( and(and(A,B),or(and(C,D),or(E,F))), Simplified ).
Simplified = and(A,B,or(and(C,D),E,F)).

?- simplify( and(and(A,B),or(and(C,and(D,E)),or(F,G))), Simplified).
Simplified = and(A,B,or(and(C,D,E),F,G)).

?- simplify( and(and(A,B),or(C,or(and(and(D,E),F),G)),and(H,I)), Simplified).
Simplified = and(A,B,or(C,and(D,E,F),G),H,I).