小编Fat*_*ize的帖子

if_/3有什么用?

该谓词if_/3似乎在Stack Overflow的Prolog部分的少数主要贡献者中相当受欢迎.

这个谓词是这样实现的,由@false提供:

if_(If_1, Then_0, Else_0) :-
   call(If_1, T),
   (  T == true -> call(Then_0)
   ;  T == false -> call(Else_0)
   ;  nonvar(T) -> throw(error(type_error(boolean,T),_))
   ;  /* var(T) */ throw(error(instantiation_error,_))
   ).
Run Code Online (Sandbox Code Playgroud)

但是,我一直无法找到这个谓词的作用的清晰,简单和简洁的解释,以及它与Prolog的经典if-then-else结构相比有什么用处if -> then ; else.

我发现的大多数链接直接使用这个谓词,并且提供了很少的解释,为什么它被使用,Prolog中的非专家可以轻松理解.

if-statement prolog logical-purity

30
推荐指数
2
解决办法
902
查看次数

CLPFD和无限可数域

I #> 0, I #< 10, indomain(I).
Run Code Online (Sandbox Code Playgroud)

以前的代码显然执行以下操作:

I = 1 ;
I = 2 ;
I = 3 ;
I = 4 ;
I = 5 ;
I = 6 ;
I = 7 ;
I = 8 ;
I = 9.
Run Code Online (Sandbox Code Playgroud)

以下代码不起作用(参数未充分实例化):

I #> 0, indomain(I).
Run Code Online (Sandbox Code Playgroud)

现在我明白在这种情况下存在无限数量的可能绑定I,并且CLPFD适用于有限域,顾名思义.

但是我不明白为什么在这种特殊情况下存在这种限制.是不是可以列举从最小到最大规范的可能解决方案,并获得以下内容:

I = 1 ;
I = 2 ;
I = 3 ;
.
.
.
Run Code Online (Sandbox Code Playgroud)

即使存在多个变量的问题,也可以说:

0 #< I, I #< J, label([I,J]).
Run Code Online (Sandbox Code Playgroud)

为什么不可能实现它,以便发生以下行为:

I = 1,
J …
Run Code Online (Sandbox Code Playgroud)

prolog clpfd

9
推荐指数
1
解决办法
352
查看次数

findall/3在其结果列表中创建新的,不相关的变量

?- permutation([A,B,C],Z).
Z = [A, B, C] ;
Z = [A, C, B] ;
Z = [B, A, C] ;
Z = [B, C, A] ;
Z = [C, A, B] ;
Z = [C, B, A] ;
false.
Run Code Online (Sandbox Code Playgroud)

说得通.我可以处理排列,[A,B,C]并且排列包含与in相同的元素[A,B,C],因此我对这些元素所做的一切都将应用于我的原始列表.

现在:

?- findall(X, permutation([A,B,C], X), Z).
Z = [[_G1577, _G1580, _G1583], [_G1565, _G1568, _G1571], [_G1553, _G1556, _G1559], [_G1541, _G1544, _G1547], [_G1529, _G1532, _G1535], [_G1517, _G1520, _G1523]].
Run Code Online (Sandbox Code Playgroud)

为什么??为什么findall/3给我列出包含完全不相关的变量的列表,而不是A,B,C?这些列表Z甚至没有相互关联,所以我得到的结果实际上只有6个长度为3的随机列表,这完全不是我所查询的.

有了这种行为,我们得到如下荒谬的结果:

?- findall(X, …
Run Code Online (Sandbox Code Playgroud)

prolog prolog-findall

8
推荐指数
2
解决办法
199
查看次数

获取调用谓词的名称

假设我正在研究这个玩具示例(问题的重点显然不是解决这个示例):

p([]).
p([H|T]) :- H = 0, call_predicate(p,T).

call_predicate(Name,Arg) :- call(Name,Arg).
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都很好。现在假设我想添加一个call_predicate/1不需要谓词名称的谓词:

call_predicate(Arg) :- Name = ??, call(Name,Arg).
Run Code Online (Sandbox Code Playgroud)

这样我就可以使用 in p: call_predicate(T),隐式地知道我想调用同名的谓词。

那么问题是,在知道这是调用的谓词的名称的情况下,如何p从 中检索名称?call_predicate/1call_predicate/1

一个类似的问题是,如果它比第一个更容易,我如何检索执行中一次所处的当前谓词的名称?

reflection prolog swi-prolog

5
推荐指数
1
解决办法
706
查看次数

使用Gnuplot对缺失值进行着色间隔

我有时态数据,其中一些时间间隔仅包含缺失值.我想明确地显示那些缺失的值间隔.

现在,我的解决方案是检查值是否是NaN这样的:

plot file_name using 1:(stringcolumn(num_column) eq "NaN" ? 1/0 : column(num_column)) with lines,\
    "" using 1:(stringcolumn(num_column) eq "NaN" ? 1000 : 1/0) with points
Run Code Online (Sandbox Code Playgroud)

这将导致绘制点y = 1000而不是缺失值的行,这会得到以下结果:

在此输入图像描述

然而,这并不理想,因为a)我需要指定y绘制点的值,b)它非常难看,特别是当数据集的时间较长时.

我想生产这样的东西:

在此输入图像描述

也就是说,用一种颜色完全填充这个间隔(可能与我的图像不同,有一些透明度).请注意,在这些示例中,只有一个缺失值的间隔,实际上在一个图上可以有任意数量的缺失值.

gnuplot

5
推荐指数
1
解决办法
326
查看次数

Prolog CLPFD中的整数和无限循环列表

假设我想表示这样的整数:integer:Sign:[FirstDigit,SecondDigit,...].例如,42表示为integer:positive:[4,2].

我需要一个谓词,它根据这个表示生成整数的值,反之亦然.

这是我想出的:

integer_value_('integer':Sign:[H],E) :-
    H in 0..9,
    (
        Sign = 'positive',
        E #= H
        ;
        Sign = 'negative',
        E #= -H
    ).
integer_value_('integer':Sign:[H,I|T],E) :-
    H in 0..9,
    length([I|T],L),
    (
        Sign = 'positive',
        E #= F + H * 10^L
        ;
        Sign = 'negative',
        E #= F - H * 10^L
    ),
    integer_value_('integer':Sign:[I|T],F).
Run Code Online (Sandbox Code Playgroud)

这按预期工作.然而,它具有接受诸如integer:positive:[0,1]在列表开头的前导零之类的事情的不幸特性.当我使用integer_value_(I,J), label([J]).以下列举所有可能的整数时,这尤其成问题:带有前导零的那些也会出现.

然后,我试图通过integer_value_仅使用除第一个数字之外的所有数据来解决这个问题,并使用integer_value第一个数字(请记住,我们需要容纳0表示只包含0的列表):

integer_value('integer':Sign:[H],E) :-
    abs(E) #< 10,
    abs(E) #> -1,
    integer_value_('integer':Sign:[H],E).
integer_value('integer':Sign:[H,I|T],E) :-
    H …
Run Code Online (Sandbox Code Playgroud)

prolog infinite-loop clpfd failure-slice

5
推荐指数
1
解决办法
153
查看次数

is_list/1和自由变量

这是第一个观察:

?- is_list([]), is_list([_,_,_]).
true.
Run Code Online (Sandbox Code Playgroud)

这是另一个观察:

?- [] = _, [_,_,_] = _.
true.
Run Code Online (Sandbox Code Playgroud)

因此,为什么会is_list/1这样实施

?- is_list(_).
false.
Run Code Online (Sandbox Code Playgroud)

要么

?- is_list([_|_]).
false.
Run Code Online (Sandbox Code Playgroud)

何时_可以清楚地统一列表?这不是逻辑上更健全的true吗?

SWI-Prolog的文档中is_list/1,注释说: 

在5.0.1之前的版本中,is_list/1只检查[][_|_]proper_list/1有电流的作用is_list/1.目前的定义符合事实上的标准.

为什么这是事实上的标准?

list prolog unification logical-purity

5
推荐指数
1
解决办法
314
查看次数

CLP(FD)和dif/2中的重复约束

在SWI-Prolog中,以下查询给出了以下结果:

?- X mod 2 #= 0, X mod 2 #= 0.
X mod 2#=0,
X mod 2#=0.
Run Code Online (Sandbox Code Playgroud)

虽然正确,但显然不需要第二个约束

同理:

?- dif(X,0), dif(X,0).
dif(X, 0),
dif(X, 0).
Run Code Online (Sandbox Code Playgroud)

有没有办法避免这种重复约束?(显然,最正确的方法是不编写导致这种情况的代码,但并不总是那么容易).

prolog clpfd

5
推荐指数
0
解决办法
183
查看次数

在 Prolog 中正确使用集合

在 Prolog 中,集合似乎是使用列表来表示的。

例如,以下是union/3SWI-Prolog 的实现:

union([], L, L) :- !.
union([H|T], L, R) :-
    memberchk(H, L), !,
    union(T, L, R).
union([H|T], L, [H|R]) :-
union(T, L, R).
Run Code Online (Sandbox Code Playgroud)

然而这个谓词不是很有声明性,例如:

?- union([1,2,3],X,[1,2,3,4]).
X = [1, 2, 3, 4].
Run Code Online (Sandbox Code Playgroud)

这应该留下一些选择点,或者:

?- union(X,[1,2],[1,2,3,4]).
<infinite loop>
Run Code Online (Sandbox Code Playgroud)

这甚至不起作用!

除此之外,我们还发现以下问题:

?- union([1,2,3],[4,5],[1,2,3,5,4]).
false.

?- union([1,1,1],[4,5],[1,1,1,4,5]).
true.
Run Code Online (Sandbox Code Playgroud)

如果我们真的谈论集合,这显然是错误的。

我们可以清楚地看到,使用列表来讨论集合并不简单,因为:

  • 集合没有排序,而列表则有;
  • 集合不包含重复值,而列表可以。

因此,我们要么发现作用于集合的谓词可以削减可能的解决方案(例如,联合的实现仅在集合有序的情况下才起作用),要么找到根据变量的实例化提供无用选择点的谓词(例如,联合谓词将具有作为许多选择点作为结果集的排列数)。

在 Prolog 中应该如何正确实现适用于集合的谓词?

这个问题非常笼统,并不特定于此处使用的示例union/3

list set prolog unification

5
推荐指数
1
解决办法
1550
查看次数

实现谓词的指南,如dif/2

假设我有一个谓词foo/2,它定义了它的第一个和第二个参数之间的关系.

改变这种实现的最惯用和最有效的方法是什么foo/2:

  • 如果它的两个参数都是基础的,它就像以前一样(如果关系成立则成功,否则失败).

  • 如果两个参数中的一个(或两个)都是空闲的,它会"约束"这两个参数,这样当它们接地时,将检查关系.

换句话说,如何正确地实现由dif/2任何类型的用户定义关系表现出来的行为?

listing(dif/2). 没什么帮助.

prolog prolog-dif

5
推荐指数
1
解决办法
277
查看次数