Prolog:从 DCG 生成查询

MrL*_*bob 4 call prolog 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).
Run Code Online (Sandbox Code Playgroud)

而且我有一个 DCG 可以确定有效的问题,例如“谁是约翰的兄弟”,这也很有效。

question --> ip, verb, article, noun, pronoun, name.
Run Code Online (Sandbox Code Playgroud)

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

noun(X, name).
Run Code Online (Sandbox Code Playgroud)

在这个例子中应该是

brother(X, anna).
Run Code Online (Sandbox Code Playgroud)

然后将答案作为自然语言答案返回,例如:

"the brother of anna is john"
Run Code Online (Sandbox Code Playgroud)

定义答案句的语法也没有问题。我唯一不知道的是,如何从我的 DCG 调用到我的数据库并在其中填充正确的值。我现在环顾四周 - 也许我不知道正确的搜索词 - 并且找不到与此相关的内容。

我希望你们有一些好主意!:)

谢谢你。

mat*_*mat 5

从 DCG 调用 Prolog 谓词

常规方式:使用 {}/1

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

例如:

verb --> [V], { verb(V) }.
Run Code Online (Sandbox Code Playgroud)

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

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

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

例如,你可以说:

female(anna)  --> [].
female(susan) --> [].
male(john)    --> [].
male(timmy)   --> [].
Run Code Online (Sandbox Code Playgroud)

然后您可以直接使用这些非终结符。您可以定义自动term_expansion/2执行此类转换的规则。

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

编辑:从您的评论中,我看到您的问题涉及更多。

问题是关于:

从句子构建 Prolog 目标

这是非常直接的:本质上,您只需要描述您想要的 Prolog 目标和相应句子之间的关系

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

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

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

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

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

例如:

?- phrase(sentence_goal(Goal), Sentence), Goal.
Run Code Online (Sandbox Code Playgroud)

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

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