Prolog部分匹配

时间:2019-03-14 13:13:02

标签: prolog

如果存在不能满足所有参数的规则,是否有一种标准的方法来仅对某些参数进行部分匹配?

例如,以下查询找不到解决方案:

?- query(A, B, C).
false.

但是,如果我们不尝试在C上统一,则可以找到解决方案:

?- query_best_effort(A, B, C).
A = alfa,
B = bravo ;

我有以下实现此功能的代码。但是还有更多的Prolog方法可以做到这一点吗?

fact1(alfa).
fact2(bravo).
fact3(charlie).

rule1(A) :-
    fact1(A).

rule2(B) :-
    fact2(B).

rule3(C) :-
    fact3(C),
    C \== charlie.

query(A, B, C) :-
    rule1(A),
    rule2(B),
    rule3(C).

query_best_effort(A, B, C) :-
    query_chain3(A, B, C);
    query_chain2(A, B);
    query_chain1(A).

query_chain3(A, B, C) :-
    query(A, B, C).

query_chain2(A, B) :-
    \+query_chain3(A, B, _),
    rule1(A),
    rule2(B).

query_chain1(A) :-
    \+query_chain2(A, _),
    rule1(A).

1 个答案:

答案 0 :(得分:3)

首先,对编程风格进行评论。使用析取符(;/2)时,请始终将其括在括号之间,并避免在行尾写入;。就您而言:

query_best_effort(A, B, C) :-
    (   query_chain3(A, B, C)
    ;   query_chain2(A, B)
    ;   query_chain1(A)
    ).

此推荐样式有助于提高代码的可读性。

您还可以避免使用否定(\+/1),而应使用在几个Prolog系统(一些系统,例如SICStus Prolog)中实现的*->/2 soft-cut 控制结构,将其实现为if/3内置谓词):

query_best_effort(A, B, C) :-
    (   query_chain3(A, B, C) *->
        true
    ;   query_chain2(A, B) *->
        true
    ;   query_chain1(A)
    ).

query_chain3(A, B, C) :-
    query(A, B, C).

query_chain2(A, B) :-
    rule1(A),
    rule2(B).

query_chain1(A) :-
    rule1(A).

*->/2控制结构与标准->/2控制结构不同,它允许回溯到条件中。调用query_best_effort/3谓词时,仅在query_chain2/2目标没有解决方案的情况下调用query_chain3/3谓词,并且仅在没有query_chain1/1目标的解决方案时调用query_chain3/3谓词query_chain2/2| ?- query_best_effort(A, B, C). A = alfa B = bravo yes 目标的解决方案,我认为您的意图是使用析取和否定?

通话示例:

*->/2

但是请注意,import csv with open("thetext.txt") as txt, open('theoutput.csv', 'a') as csvfile: writer = csv.writer(csvfile, delimiter=';') writer.writerow(('ID', 'Reporttext')) id = 1 for line in txt: words = line.strip().split("@@@") for word in words: writer.writerow((id, word.strip())) id += 1 就像否定一样,是一种非逻辑控制结构。