关于Prolog中复杂术语的概念问题

时间:2017-03-11 10:59:43

标签: prolog

我刚刚开始在大学学习Prolog,我有一个概念问题,我没有找到任何具体的答案:

我想要将这种语言的“哲学”内化,所以我想非常准确地理解复杂的术语是什么(或复合词)。到现在为止,我已经读到一个复杂的术语是一个仿函数而且它是正统的。我可以使用这样的复杂术语构建知识库:

love(john, sarah).

让我们说现在,我可以输入任何可能的字符串对作为“爱”的参数,除非字符串对是“john,sarah”,否则它将是假的。是的,所以对仿函数及其论证的“问题”是真的还是假的,这取决于我是否在我的知识库中特别说过,或者Prolog是否能够根据他使用规则,统一等信息来推断它

是的,从这里开始,我理解一个复杂的术语表示n个实体之间的关系是 true或false 。我不明白的是:

vertical(line(point(X,Y),point(X,Z))).

我明白什么点(X,Y)。确实。它说任何实体都通过“点”与任何其他实体相关。我不明白的是点(X,Y)如何成为线的参数!到目前为止,一个复杂的术语只是说实体是否相关。我可以理解它是一个“传统函数”,如果实体是相关的,则返回true或false。但这怎么可能是线的论点?理论上,“线”有2个参数(实体),它会说它们是否相关。现在,参数的值是真还是假?

我能理解“点(X,Y)”正在创建一个对象“点”。所以行的参数是一个“点实体”。但到目前为止,这并不是我读过的关于复杂术语的内容,所以我希望能够通过技术定义来解释嵌套案例。

(如果我使用了错误的术语或定义,我很抱歉,我是Prolog的新手)

谢谢!

3 个答案:

答案 0 :(得分:2)

  

我理解一个复杂的术语表示n个实体之间的关系在理论上是真或假[line],有2个参数(实体),它会说它们是否相关。

遗憾的是,您对“复杂术语”的解释是错误的。 Prolog使用这些术语来表示“程序”和“数据”,因此术语的解释取决于它出现的上下文以及如何使用它。

考虑你的第一个例子:

love(john, sarah).

从最后的时期(以及您在知识库的上下文中提到这一点的事实),我们知道这必须作为Prolog文件中的顶级构造出现。这些术语定义了谓词的子句。这些是“程序”:这个术语定义谓词love/2的一个子句(/2是术语的常用Prolog表示法,即参数的数量)。我们可以通过“调用”它来将其用作“程序”:

?- love(X, Y).
X = john,
Y = sarah.

在这个“程序”上下文中,我们可以说love/2是两个术语之间的关系。

但在第二个示例中,line字词出现在顶层。它嵌套在vertical/1术语中:

vertical(line(point(X,Y),point(X,Z))).

这意味着定义的“程序”是vertical/1,在术语上是一个单一的关系。 (将它称为“一组术语”更自然。在这个例子中,“垂直线的集合是两个点具有相同 X 坐标”的所有线的集合。) line/2 被定义为关系;它只是未解释的数据。我们可以致电vertical/1

?- vertical(T).
T = line(point(_G921, _G922), point(_G921, _G925)).

但不是line/2

?- line(P1, P2).
ERROR: toplevel: Undefined procedure: line/2 (DWIM could not correct goal)

摘要:只有“顶级”字词定义谓词,只有这些字词才能被解释为关系。程序中出现的其他术语只是关系所涉及的“数据”。

答案 1 :(得分:2)

这是一个很好的问题,因为Prolog许多Prolog初学者来自命令式语言的背景,这是一个基本的混乱点。我在学习Prolog时的建议通常是,#34;忘记(几乎)你所学到的关于编程的一切,并从基础知识开始#34;。

Prolog建立在可以包含零个或多个参数的术语上。 foo是一个没有参数的术语。 foo(A, B)是一个带有两个参数的术语。 foo(bar(X), bah(Y,Z))是一个带有两个参数的复杂术语(称为foo/2),其参数由术语bar/1(有一个参数)和bah/2(有两个参数)组成

即使谓词子句是Head :- Body形式的术语,也可以是规范形式的':-'(Head, Body)。当这种术语在Prolog程序中声明(在文件中静态声明,甚至动态声明)时,Prolog将其识别为谓词,因为Prolog为某些术语赋予了特殊含义,{{{在这种情况下,1}}用于谓词子句定义。但如果没有这种背景,:-仍然只是一个术语"。

在Prolog中,除了预定义的术语(例如':-'(A, B),运算符等)之外,程序员定义的术语的语义仅取决于程序员决定的内容和上下文(查询?断言?另一个术语?),用于他们的程序。

  

我明白什么点(X,Y)。确实。它说任何实体都通过" point"。

与任何其他实体相关

在Prolog中,:-是一个带有两个参数(point(X, Y))的术语,除了程序员决定之外没有任何语义含义(没有'#34;做"任何事情)然后他们在程序中使用它。如果我在Prolog提示符下输入point/2,如下:

point(X, Y)

Prolog将此视为查询,并尝试查找与?- point(1, 2). 匹配的事实或规则,并允许其成功。但是,如果我输入了:

point(1, 2)

Prolog只是看到?- foo(point(1, 2)). 上的查询查找与foo/1匹配的事实或规则,foo(_)是"只是一个术语"没有进一步的解释,除非有一个谓词子句将它放在一个上下文中。例如,如果point(1, 2)我的数据库中只有一个事实foo/1而且foo(a).没有规则,foo/1失败,因为Prolog会尝试将术语foo(point(1, 2)).(带有零参数的术语)与术语a(带有2个参数的术语)匹配,并且会失败,并且没有其他选择可以尝试。如果我有point(1, 2Y)的条款看起来像这样:

foo/1

然后,通过将foo(X) :- X = point(A,B), ... % do some things involving A and B foo(point(1,2))统一,查询X将匹配此条款的标题,然后此子句的第一行将统一point(1,2)并统一{{在此上下文中,1}}和point(1, 2) = point(A, B)A = 1不会以任何方式调用执行

假设我有以下B = 2条款:

point/2

现在,如果我查询foo/1foo(X) :- call(X), ... 将尝试调用 foo(point(1, 2)).(将其作为查询执行),Prolog将尝试查找事实或与foo/1匹配的规则。

  

我不明白的是点(X,Y)如何成为线的参数!

请记住,这只是一个术语。除非在特定上下文中使用,否则它没有语义。直到你在Prolog中以某种方式运用这个术语,除了程序员的头脑之外没有任何意义。程序员可以决定定义术语point(1, 2),该术语表示从点point(1, 2)到点line(A, B)的行。如果我们有一个术语,我们想在两个坐标A上定义一个点,我们也可以说B。通过程序员约定,这意味着,我从(point(X, Y)line(point(X1, Y1), point(X2, Y2)))指向一条线,指向(X1Y1

  

到目前为止,一个复杂的术语只是说实体是否相关。

我不确定你为什么说"直到现在"。用户决定该关系是什么,以及如何组织(复杂)术语来表示该关系。当我们说X2时,Y2可以(由程序员自行决定)代表从line(point(X1, Y1), point(X2, Y2))(X1, Y1)的一行。

  

我能理解它是一种传统功能"如果实体是相关的,则返回true或false。

事实并非如此。该术语形成传统功能" 返回 (X2, Y2)true。这只是一个术语,不会返回任何东西。正如我所提到的,在Prolog中,术语的行为确实取决于上下文。术语可以是查询,这意味着它被称为,而Prolog将尝试(通过先前声明的事实和规则/谓词)确定它是可证明的或真实的。在这种情况下,它将事实或规则与顶级术语仿函数名称相匹配。因此,如果您实际上查询 false,Prolog会查找与line(point(X1, Y1), point(X2, Y2))匹配的事实或规则并从那里开始。然后它会成功或失败,具体取决于它是否能够匹配事实,或成功完成规则。

  

但这怎么可能是线的论点? "线"从理论上讲,它有2个参数(实体),它会说它们是否相关。

line(_, _)是一个术语,根据程序员的惯例,代表从line(point(X,Y), point(X,Z))点到(X, Y)点的一行。

  

现在,论点'值是真还是假?

不,这些论点根本没有任何。它们只是定义程序员选择代表的东西的术语或结构。

  

我能理解"点(X,Y)"正在创建一个对象"指向"。

它不会创建一个对象。它只是一个代表横坐标(X, Z)和纵坐标X的点的术语。

  

因此,line的参数是一个"点实体"。

Y有两个参数,它们代表定义一条线的两个不同点(按照程序员的惯例)。如果它表示为line/2,那么"形式"没有指定点(程序员可以选择用列表表示一个点,例如line(P1, P2),或者在这种情况下,用户定义的术语[X, Y])。

  

但到目前为止,这并不是我所读到的关于复杂术语的内容,所以我希望能够通过技术定义来解释嵌套案例。

到目前为止,您对复杂的术语有什么看法?为了帮助解决这个问题,我们需要知道您所阅读的内容,这些内容似乎让您感到困惑。

<小时/> 您还没有显示任何上下文代码,所以让我们构建一些上下文来帮助理解这一点。我将选择将一个点定义为point(X, Y),并将一行显示为point(X, Y),其中line(P1, P2)P1为点。因此,我也可以将行表示为P2。这是我作为程序员的选择。

如何在Prolog中定义有效点?我可以用术语line(point(X1, Y1), point(X2, Y2))来定义它。但point(X, Y)X是什么?他们怎么定义?我可能会强制他们是数字。所以这是一个有效Y的规则:

point

在Prolog中我可以简化一下,因为我可以使用复杂的术语作为子句的头部:

valid_point(P) :-
    P = point(X, Y),   % a Point looks like point(X, Y)
    number(X),
    number(Y).

如果valid_point(point(X, Y)) :- number(X), number(Y). valid_point(point(X, Y))都是数字,那么X只会成功。如果您要问Prolog如果Y是一个有效点(查询(point(3, 5.2),那么它会成功(例如&#34; true&#34;)。如果您要问Prolog是否{{1} }是一个点(查询valid_point(point(3, 5.2)).,它会失败(说&#34;假&#34;)。

现在让我们定义一条线。一条线由任意两点定义,因此我们可以将其表示为point(a, 3)一词,其中valid_point(point(a, 3)).line(P1, P2)是不相同的有效点。因此,我们可以如下定义有效行。我将详细说明如何统一和使用术语:

P1

再次,Prolog让我使用复合术语来进一步简化:

P2

此规则表明valid_line(Line) :- Line = line(P1, P2), P1 = point(X1, Y1), % P1 is a valid point valid_point(P1), P2 = point(X2, Y2), % P2 is a valid point valid_point(P2), ( X1 =\= X2 ; Y1 =\= Y2 ). valid_line(line(point(X1, Y1), point(X2, Y2))) :- valid_point(point(X1, Y1)), valid_point(point(X2, Y2), ( X1 =\= X2 ; Y1 =\= Y2 ). 形成有效行,如果它们是有效点,且point(X1, Y1)point(X2, Y2)不相等,或X1 }和X2不相等。

让我们继续更高层次的规则。如果线条有效并且其点具有相同的横坐标,则线条垂直。我们可以创建一个规则,Y1如果行参数是垂直的则成功,否则失败:

Y2

我们可以通过统一条款开头的横坐标来缩写:

vertical_line

在上述所有示例中,我将规则名称与数据结构名称分开。所以我通常vertical_line(line(point(X1, Y1), point(X2, Y2)) :- valid_line(line(point(X1, Y1), point(X2, Y2)), X1 = X2. ,但vertical_line(line(point(X, Y1), point(X, Y2))) :- valid_line(line(point(X, Y1), point(X, Y2)). 代表一条线的结构。没有理由他们必须分开,但它可以帮助避免混淆,如果他们是。即使它们是相同的,Prolog是否作为查询执行它将取决于上下文。例如,我可以定义一个规则valid_line/1,只有当参数是数字时才能成功:

line/2

然后我可以查询:

point/2

但是,如果我然后定义point(X, Y) :- number(X), number(Y).

?- point(1, 3).
true

?- point(a, 7).
false.

执行统一line/2时,这不会强制执行有效点(调用line(P1, P2) :- P1 = point(X1, Y1), P2 = point(X2, Y2), ( X1 =\= X2 ; Y1 =\= Y2 ). )。这是因为Prolog中的谓词不是函数,并且不会那样。如果我要查询,point/2它可能会产生错误,因为我试图用数字与P1 = point(X1, Y1)比较坐标。表达式line(point(a, 3), point(c, d))实际上是Prolog中的术语(=\=)/2。正如我上面提到的,当Prolog进行呼叫时,它位于顶级术语,在这种情况下是P1 = point(X1, Y1),而'='(P1, point(X1, Y1))是&#34;只是一个术语&#34;并没有在这种背景下调用。我可以拨打'='但如下:

point(X1, Y1)

然后Prolog会更优雅地检查点的有效性(根据我定义的point/2谓词)。但我并不认为这与单独定义line(P1, P2) :- P1 = point(X1, Y1), call(P1), P2 = point(X2, Y2), call(P2), ( X1 =\= X2 ; Y1 =\= Y2 ). 谓词一样清晰。

答案 2 :(得分:0)

在一个术语中,变量按名称​​唯一。所以,事实

vertical(line(point(X,Y),point(X,Z))).

仅根据P1,P2的ascissa的身份说明未解释的术语(line(P1,P2))的属性。

现在,如果这有任何意义,它与特定的应用领域有关,但我们对此一无所知,排除了平庸的几何直觉......