谓词从Prolog中删除复合词中的某些术语

时间:2017-05-09 22:33:30

标签: prolog

我想写一个Prolog谓词,它接受一个复合词作为其参数,并输出这个复合词,删除了一些嵌套词。例如,让我们说我有一个复合词:

outer_term(level_one(level_two_a(X), level_two_b(Y)), level_one(level_two_b(Z))).

我想编写一个谓词extract_terms/2,它将使用这个术语并在没有出现level_two_a/1的情况下返回它。

extract_terms(Term, ExtractedTerm) :-
       *** Prolog Magic ***.

Prolog中是否有内置(或半内置)方式?如果没有,我该怎么做呢?我遇到的一种方法是使用=../2运算符将Term转换为列表,然后以某种方式使用某些内置谓词(如subtract/3)来删除我想要的谓词。我遇到的麻烦是使用嵌套术语作为项目的列表来使用它。

我很感激任何想法,谢谢。

1 个答案:

答案 0 :(得分:4)

首先,一般准则:

模式匹配表示 的所有内容应通过模式匹配来表达。

你之前问过similar question,虽然它有点简单。不过,让我们先考虑一个更简单的案例:你说一个动词短语的可能实例是:

VP = vp(vp(verb(making), adj(quick), np2(noun(improvements))))

并且您想要提取动词。嗯,最简单的方法是使用模式匹配,或者更常见的是统一,如下所示:

?- VP = vp(vp(verb(making), adj(quick), np2(noun(improvements)))),
   VP = vp(vp(Verb, _, _)).

这会产生:

Verb = verb(making).

因此,我们通过统一成功地从这样的短语中“提取”了verb(making)

现在您要在这个问题中考虑稍微复杂的任务:此时,您可能想知道您是否选择了数据的良好表示。经常使用甚至(=..)/2的必要性通常表示您的代表性存​​在问题,因为这可能意味着您已经失去了对数据可能形状的跟踪或控制。

在这个具体案例中,您举例说明:

outer_term(level_one(level_two_a(X), level_two_b(Y)), level_one(level_two_b(Z))).

并且您想删除level_two_a的出现次数。您现在当然可以开始混淆(=..)/2,这需要将这些术语转换为列表,然后在这些列表上进行一些推理,以及从列表转换回此类结构的第二次转换。这不是我们想要处理数据的方式。除了其他缺点之外,它还会排除我们期望从关系中获得的更一般的使用模式。

相反,让我们修复数据表示,以便我们可以干净地区分不同的情况。例如,我们不需要“硬编码”我们需要区分仿函数 的情况的参数,让我们区分 explicit :我们希望能够区分,通过模式匹配,从第2级开始第1级。

因此,以下表示表明了自己:

outer_term([level(1, [level(2, X),
                      level(2, Y)]),
            level(1, [level(2, Z)])]).

这可能需要一些额外的属性,例如ab,并且我将此表示扩展为将这些属性表示为一个简单的练习。一般的想法应该是清楚的:我们已经实现了一个统一的表示,我们可以很容易地用符号来推理。

现在可以很容易地描述这些级别的(可能嵌套的)列表与没有“级别2”元素的级别之间的关系

without_level_2(Ls0, Ls) :-
        phrase(no_level_2(Ls0), Ls).

no_level_2([]) --> [].
no_level_2([L|Ls]) -->
        no_level_2_(L),
        no_level_2(Ls).

no_level_2_(level(2,_))   --> [].
no_level_2_(level(L,Ls0)) --> [level(L,Ls)],
        { dif(L, 2),
          without_level_2(Ls0, Ls) }.

有关此形式主义的更多信息,请参阅

示例查询:

?- outer_term(Ts0),
   without_level_2(Ts0, Ts).

产量:

Ts = [level(1, []), level(1, [])] .

请注意,要真正从此表示中受益,您需要首先通过使用或生成此类形状的术语来获取它。一旦确保了这一点,您可以方便地坚持模式匹配以区分案例。在这种方法的主要优点中,我们发现便利性性能通用性。例如,我们可以使用上面显示的DCG,不仅可以提取,还可以使用生成这种形式的术语:

?- length(Ls0, _), without_level_2(Ls0, Ls).
Ls0 = Ls, Ls = [] ;
Ls0 = [level(2, _56)],
Ls = [] ;
Ls0 = Ls, Ls = [level(_130, [])],
dif(_130, 2) ;
Ls0 = [level(_150, [level(2, _164)])],
Ls = [level(_150, [])],
dif(_150, 2) .

这是一个真正的关系,可用于所有方向。出于这个原因,我在谓词名称中避免了命令式名称,例如“extract”,“remove”等,因为这些名称始终建议使用特定的方向,而不是正义的谓词的普遍性。