これは私の一時的な解決策です。これはまだ理想的ではなく、最初の深度レベルで関数を「平坦化」するので、数式に他の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)を持つすべてのノードを1つのノードにまとめると同時に、異なるキーを持つノードを保持します(ORとANDを組み合わせることはありません)。私はすべてのシナリオ(たとえば、[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]], !.
2つのパラメータがありますか? 1つは、単純化されたバージョンを "返す"? –
はい、そうです。私は統合を使用する代わりに内部の関数を解析する必要があります。私はかなり混乱しました! – Dodicin
まず、処理したい用語の種類とその場合の結果を決定する必要があります。たとえば、 'and(and(A、B)、and(C、D))'は 'と(A、B、C、D)'と容易に理解できます。しかし、 'と(と(A、B)、((C、D)、E))'はどうでしょうか?表現を単純化し、引数を組み合わせることを目指していますか?一度それを決めたら、再帰的に考えてみてください。 (A、B)、式を簡略化する: - 簡略化する(A)、...、簡略化する(B)、...など。 – lurker