2

考虑以下列表:

[我的名字是杰克鲍尔]

我想将其统一为以下模式:

[我的,姓名,是,姓名]

这样变量 Name 最后的值就是“jack baur”。该变量在这里用作某种通配符,应该与未知数量的原子/列表成员统一。

重要的:

  • 变量/通配符并不总是在最后
  • 可能有多个变量/通配符

目前我有这样的事情:

rule([my,name,is,Name],[hello,Name]).

% Sentence is a list (e.g. [my,name,is,jack,baur]
answer(Sentence,Response) :-
    rule(Sentence,ResponseList),
    atomic_list_concat(ResponseList,' ',Response).

显然,这只适用于Name恰好是一个词,而不是两个词。

我将如何在 Prolog 中解决这个问题?

4

2 回答 2

1

这里有 DCG 的可能性。挺干净的,我觉得

list(L) --> {length(L, _)}, L.

rule(R) -->
    [my, name, is], list(Name),
    [and, i, live, in], list(Country),
    {flatten([hello, Name, of, Country],R)}.

rule([hello|Name]) -->
    [my, name, is], list(Name) .

answer(Sentence, Response) :-
    phrase(rule(Response), Sentence), !.

接着就,随即

?- answer([my, name, is, bill, the, kid, and, i, live, in, new, york],R).
R = [hello, bill, the, kid, of, new, york].

这里的基本产生是 list//1,它匹配任何确定长度的标记列表。

注意:应避免 A、B 都未list(A),list(B),绑定如果中间有代币也没关系,比如list(A),[and],list(B),

于 2012-12-26T11:28:01.237 回答
1

您需要自定义统一算法,例如:

unify([], []).
unify([X|L], R) :-
    (var(X) ->
        % unify the variable X with some prefix of R
        append(X, Tail, R),
    ;
        R = [X|Tail],
    ),
    unify(L, Tail).

用法:

1 ?- unify([i, am, a, Profession, and, i, Verb, it],
           [i, am, a, prolog, programmer, and, i, like, it]).
Profession = [prolog, programmer],
Verb = [like].

L为了效率,该算法只允许变量出现。我将把原子粘贴在一起的问题留给你,因为你似乎已经解决了这个问题。

请注意,当前版本允许变量匹配零个原子,但您可以轻松添加约束来禁止它。

于 2012-12-25T14:08:21.613 回答