如果在任一参数上应用相同的函数,我必须在输入中编写一个给出二进制公式(在本例中为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并且两个参数都不是复合,那么它意味着简化函数是相同的。我该如何进一步处理?
谢谢!
答案 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).