您的帖子中有几个重叠的问题和问题,可能太多了,无法在一个帖子中连贯地解决您完全满意的问题。
因此,我想先说明一些一般原则,然后在此基础上对您发布的代码进行一些具体的评论。
首先,我想谈谈我认为在您的情况下最重要的问题:
LP ⊆ 中电
这仅仅意味着 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(ℛ) 约束!
因此,您的第一个示例已经无法单独工作。(此外,您在子句 head: 中有语法错误factorial (
,因此它也根本无法编译。)
当您学习使用约束求解器时,请查看它提供的谓词。例如,CLP(ℛ) 提供{}/1
了一些其他谓词,并且有一个专用的语法来说明关于浮点数的关系(在这种情况下)。
其他约束求解器提供自己的谓词来描述其各自领域的实体。例如,CLP(FD) 提供(#=)/2
了一些其他谓词来推理整数。dif/2
让你推理任何Prolog 术语。等等。
从程序员的角度来看,这与使用 Prolog 系统的任何其他谓词完全相同,无论它是内置的还是源自库。原则上,都是一样的:
像这样的目标list_length(Ls, L)
可以理解为:“列表的长度 Ls
是 L
。”
类似的目标{ X = A + B }
可以理解为:数字X
等于和 的总和。例如,如果您使用 CLP(Q),很明显我们在这种情况下讨论的是有理数。A
B
在您的第二个示例中,子句的主体是形式的连词(A, B)
,其中A
是 CLP(ℛ) 约束,并且B
是形式的目标factorial(PrevN, NewF)
。
重点是:CLP(ℛ) 约束也是一个目标!一探究竟:
?- write_canonical({a,b,c})。
{','(a,','(b,c))}
真的。
因此,您只是使用{}/1
from library(clpr)
,这是它导出的谓词之一。
你是对的,PrevN
属于NewF
约束。但是,factorial(PrevN, NewF)
它不是CLP(ℛ) 实现的用于对浮点数进行推理的迷你语言的一部分。因此,您不能将此目标拉入特定于 CLP(ℛ) 的部分。
从程序员的角度来看,CLP 的一个主要吸引力在于它完全无缝地融入了“正常”逻辑编程,以至于实际上几乎无法将其与它区分开来:约束只是谓词,写下来就像所有其他目标。
是否将库谓词标记为“约束”几乎没有什么区别:所有谓词都可以视为约束,因为它们只能约束答案,永远不要放松它们。
请注意,您发布的两个示例都是递归的!这完全没问题。事实上,递归谓词很可能是您将来使用约束的大多数情况。
但是,对于factorial的具体情况,Prolog 系统的CLP(FD)约束可能更合适,因为它们完全致力于对 integers进行推理。