用Prolog在CLP(R)中编写递归函数的正确方法



我对CLP在Prolog中的工作方式感到非常困惑。我不仅发现很难看到它的好处(我确实在特定的情况下看到了它,但发现很难概括这些好处),更重要的是,我很难想出如何正确地编写递归谓词。以下哪项是CLP(R)方式的正确形式?

factorial(0, 1).
factorial(N, F):- {
N > 0,
PrevN = N - 1,
factorial(PrevN, NewF),
F = N * NewF}.

factorial(0, 1).
factorial(N, F):- {
N > 0,
PrevN = N - 1,
F = N * NewF},
factorial(PrevN, NewF).

换句话说,我不确定什么时候应该在约束之外编写代码。对我来说,第一种情况似乎更符合逻辑,因为PrevNNewF属于约束。但如果这是真的,我很好奇在递归函数中使用约束之外的谓词在哪些情况下有用。

你的帖子中有几个重叠的问题,可能太多了,无法在一篇帖子中连贯地解决,让你完全满意。

因此,我想首先陈述一些一般原则,然后—基于此;对你发布的代码做一些具体的评论。

首先,我想谈谈我认为在你的情况下最重要的一点:

LP&substeq;CLP

这意味着CLP可以被视为逻辑编程(LP)的超集。是否将其视为适当的超集,或者事实上,将它们视为表示同一概念更有意义,这在一定程度上是有争议的。在我个人看来,没有约束的逻辑编程比有限制的更难理解,可用性也更低。考虑到即使是最早的Prolog系统也有像dif/2这样的约束,以及像;(=)/2完全符合"约束"的概念,如果边界存在的话,对我来说至少有点人为,这表明:

LP&近似值;CLP

尽管如此,与CLP(任何类型)合作时的关键概念是约束可用作谓词,并像所有其他谓词一样在Prolog程序中使用。

因此,无论您的目标是factorial(N, F)还是{ N > 0 },至少在原则上都是相同的概念:两者都意味着保持

请注意语法:CLP(ℛ)约束的形式为{ C },即;前缀表示法中的{}(C)

请注意,目标factorial(N, F)而不是CLP(ℛ)约束!以下两者都不是:

?-{阶乘(N,F)}。错误:未处理的异常:type_ERROR({factorial(_3958,_3960)},…)

因此,{ factorial(N, F) }也是而不是CLP(ℛ)约束!

因此,您的第一个示例已经无法单独使用了。(此外,子句头中有一个语法错误:factorial (,因此它也根本无法编译。)

学习使用约束求解器时,请查看它提供的谓词。例如,CLP(ℛ)提供了{}/1和其他一些谓词,并有一个专用的语法用于声明关系;持有大约浮点数(在这种情况下)。

其他约束求解器提供其自己的谓词,用于描述其<em]各自>域的实体。例如,CLP(FD)提供了(#=)/2和其他一些谓词来推理整数dif/2允许您推理任何Prolog术语。等等。

从程序员的角度来看,这与使用Prolog系统的任何其他谓词完全相同,无论它是内置的还是源于库。原则上,一切都是一样的:

list_length(Ls, L)这样的目标可以理解为:"列表的长度LsL。">

{ X = A + B }这样的目标可以读作:数字X等于A和;B。例如,如果您正在使用CLP(Q),很明显,我们在这里谈论的是有理数;案例

在第二个示例中,子句的正文是形式为(A, B)连词,其中A是CLP(&Rscr;)约束,B是形式factorial(PrevN, NewF)的目标。

重点是:CLP(&Rscr;)约束是也是目标!看看:

?-write_canonic({a,b,c})。{','(a,',',(b,c))}是的

因此,您只需使用library(clpr)中的{}/1,这是它导出的谓词之一。

您认为PrevNNewF属于约束是正确的。但是,factorial(PrevN, NewF)不是CLP(&Rscr;)实现的用于对浮点数进行推理的迷你语言的一部分。因此,不能将此目标引入CLP(&Rscr;)特定部分。

从程序员的角度来看,CLP的一个主要吸引力在于它完全无缝地融入中,以至于事实上几乎无法将其与;it:约束只是谓词,并且像所有其他约束一样写下来;目标。

是否将库谓词标记为"约束"几乎没有任何区别:所有谓词都可以被视为;约束,因为它们只能约束答案,所以永远不要放松它们。

请注意,您发布的两个示例都是递归的!这太完美了;好的。事实上,递归谓词可能是大多数使用的情况;未来的制约因素。

但是,对于阶乘的具体情况,Prolog系统的CLP(FD)约束可能是更好的;适合,因为他们完全致力于推理整数

相关内容

  • 没有找到相关文章

最新更新