Prolog:从 DCG 生成查询

Prolog: generate queries out of DCG

我目前有一个小型 Prolog 数据库,其中包含一些人和一些关系谓词。例如:

female(anna).
female(susan).

male(john).
male(timmy).

siblings(anna, susan).
siblings(anna, john).
siblings(susan, john).

sibling(X, Y) :- siblings(X, Y) ; siblings(Y, X).

%X is brother of Y
brother(X, Y) :- male(X), sibling(X, Y).

我有一个 DCG 可以确定有效的问题,例如 "who is the brother of john",效果也不错。

question --> ip, verb, article, noun, pronoun, name.

现在我想让我的程序用这样的名词和名字调用我的家庭数据库:

noun(X, name).

在这个例子中应该是

brother(X, anna).

然后 return 作为自然语言答案的答案,例如:

"the brother of anna is john"

定义答案句的语法也没有问题。我唯一不知道的是,如何从我的 DCG 调用我的数据库并在其中填充正确的值。我环顾四周已经有一段时间了——也许我不知道正确的搜索词——但找不到与此相关的东西。

希望大家多多指教! :)

谢谢。

从 DCG 调用 Prolog 谓词

常规方式:使用{}/1

使用非终结符 {}//1 从 DCG 中调用任意 Prolog 目标。

例如:

verb --> [V], { verb(V) }.

这定义了一个非终结符verb//1。这个 DCG 描述了一个由元素 V 组成的列表,使得 verb(V) 成立,其中 verb/1 是一个普通的 Prolog 谓词。

在某种意义上甚至更规律:始终使用 DCG!

请注意,还有第二种方法可以做到这一点,从某种意义上说,它更容易理解:您可以简单地将一切变成DCG非终结符!

例如,您可以说:

female(anna)  --> [].
female(susan) --> [].
male(john)    --> [].
male(timmy)   --> [].

然后您可以直接使用这些非终结符。您可以定义一个 term_expansion/2 规则来 自动 .

在您的特定情况下,使用 {}/1 可能更可取,因为您已经拥有现有的 Prolog 事实和。但在某些情况下,始终使用 DCG 是更可取的。

编辑:从您的评论中,我发现您的问题有点复杂。

问题是关于:

从句子构建 Prolog 目标

这非常简单:本质上,您只需要描述您想要的 Prolog 目标与相应句子之间的关系

我们通过向 DCG 引入一个新参数来做到这一点,该参数将表示需要执行以回答句子的 Prolog 目标。在您的示例中,您希望将句子 "Who is the brother of susan?" 与 Prolog 谓词 brother(X, susan) 的调用相关联。您已经有一个描述此类句子的非终结符 sentence//0。你只需要明确这些句子对应的目标即可。例如:

sentence_goal(noun(X, name)) --> ip, v, a, noun, p, name.

此处仅用于说明原理;我并不是说这已经是完整的解决方案。重点只是表明您可以用与所有其他项完全相同的方式推理 Prolog 目标。

然后您可以分两个阶段调用实际目标:

  1. 首先,使用这个新的非终结符 sentence_goal//1
  2. 将给定的句子与目标联系起来
  3. 直接调用目标,使用call/1或直接调用。

例如:

?- phrase(sentence_goal(Goal), Sentence), Goal.

在您的情况下,剩下的就是将这些句子与您要调用的 Prolog 目标相关联,例如 brother_of/2

None 这需要任何副作用 (write/1)!相反,专注于描述句子和目标之间的关系,让 Prolog 顶层为您打印。