Prolog-参数未实例化

Prolog-参数未实例化,prolog,clpfd,Prolog,Clpfd,我试图理解Prolog是如何工作的。我正在使用SWI Prolog。 下面是一些代码: forall(C1,C2) :- \+ (C1, \+ C2). foo(N) :- N < 10. bar(N) :- N > 5. foobar(N) :- forall(foo(N),bar(N)). 但当我试图查看所有可能的值时,我得到一个错误: ?- foobar(N). ERROR: </2: Arguments are not sufficiently instanti

我试图理解Prolog是如何工作的。我正在使用SWI Prolog。 下面是一些代码:

forall(C1,C2) :- \+ (C1, \+ C2).

foo(N) :- N < 10.

bar(N) :- N > 5.

foobar(N) :- forall(foo(N),bar(N)).
但当我试图查看所有可能的值时,我得到一个错误:

?- foobar(N).
ERROR: </2: Arguments are not sufficiently instantiated
?-foobar(N)。

错误:基本上,您正在编写一个检查全局含义的程序:

forall N, if N < 10 then N > 5
但是,如果您尝试将该查询提供给prolog解释器,它将输出错误:

?- \+ ( N < 10, \+ ( N > 5 ) ).
ERROR: </2: Arguments are not sufficiently instantiated
但对于一个大型域,这将是非常低效的(它将需要对域的每个元素进行回溯)

如果您想对有限域(即整数)进行推理,您可以使用@Lower建议的库。这种方法更有效,因为它有关于区间推理、区间交集等的规则

您必须用CLP操作员
\
\+
替换
\
\/\
。让我们试试看:

?- use_module(library(clpfd)).
?- #\ ( N #< 10 #/\ #\ ( N #> 5 ) ).
N+1#=_G11193,
N#>=6#<==>_G11205,
10#>=_G11193#<==>_G11217,
_G11217 in 0..1,
_G11217#/\_G11244#<==>0,
_G11244 in 0..1,
#\_G11205#<==>_G11244,
_G11205 in 0..1.
?-使用_模块(库(clpfd))。
?-(N<10/(N>5))。
N+1#=_G11193,
N#>=6#u G11205,
10#>=_G11193#u G11217,
_G11217在0..1中,
_G11217#/U G11244#0,
_G11244在0..1中,
#\_G11205#U G11244,
_G11205在0..1中。

这可能有点难理解,但在许多其他事情中,它告诉你你正在寻找的答案,那就是N的域:
N#>=6
TL;DR.Prolog有很好的代数性质,只要你坚持它的逻辑纯核心


有关详细信息,请阅读以下有关StackOverflow的序言问题的优秀答案:


  • /2
    运算符要求所有参数都具有特定值(实例化)才能工作。因此,如果
    N
    没有值(未实例化),则
    N<10
    将生成该错误。如果您试图生成具有某些约束的可能值,您可能希望使用CLPFD库,然后您可以使用
    N#<10
    ,等等。您的意思是什么?@mat:在遇到实际上不会声称有任何错误的实例化错误之前,首先反对产生错误答案的程序怎么样?@false:在我看来,这个网站上此类问题太多了,大多数问题都可以通过使用更多的声明性谓词轻松解决。我想奖励那些传播更优雅方法的用户,他们通常会给出更正确、更通用的解决方案。150分是鼓励这一点的第一个赞赏信号。对于更重要的贡献,例如非常优雅的解决方案,我会给出200分或更多。显然,我已经不得不证明第三个是正确的了。以这种方式给予赏金一点也不好玩。
    ?- \+ ( N < 10, \+ ( N > 5 ) ).
    ERROR: </2: Arguments are not sufficiently instantiated
    
    ?- N=5, \+ ( N < 10, \+ ( N > 5 ) ).
    false.
    
    ?- N=6, \+ ( N < 10, \+ ( N > 5 ) ).
    N = 6.
    
    ?- between(1, 12, N), \+ ( N < 10, \+ ( N > 5 ) ).
    N = 6 ;
    N = 7 ;
    N = 8 ;
    N = 9 ;
    N = 10 ;
    N = 11 ;
    N = 12.
    
    ?- use_module(library(clpfd)).
    ?- #\ ( N #< 10 #/\ #\ ( N #> 5 ) ).
    N+1#=_G11193,
    N#>=6#<==>_G11205,
    10#>=_G11193#<==>_G11217,
    _G11217 in 0..1,
    _G11217#/\_G11244#<==>0,
    _G11244 in 0..1,
    #\_G11205#<==>_G11244,
    _G11205 in 0..1.