Prolog 描述相对于关系排序的整数序列的最一般的高阶约束

Prolog 描述相对于关系排序的整数序列的最一般的高阶约束,prolog,clpfd,topology,meta-predicate,Prolog,Clpfd,Topology,Meta Predicate,在CLP(FD)中,我们经常需要声明:“这是一个整数和有限域变量的列表,按(有时:严格地)升序/降序排列。” 是否有任何CLP(FD)系统为该任务提供通用(可参数化)内置约束 SWI Prolog提供了一个名为chain/2的约束,它与我正在寻找的类似。但是,名称过于具体,无法包含约束可以描述的所有关系(例如:#Hoogle不是很有用,但是 因此,这是列表的一种特殊折叠形式,但它不适用于长度列表次,而适用于更少的一次 在名称上并不完全通用,但在签名上。也许坚持使用最通用的名称没有多大帮助。否则我

在CLP(FD)中,我们经常需要声明:“这是一个整数和有限域变量的列表,按(有时:严格地)升序/降序排列。”

是否有任何CLP(FD)系统为该任务提供通用(可参数化)内置约束


SWI Prolog提供了一个名为
chain/2
的约束,它与我正在寻找的类似。但是,名称过于具体,无法包含约束可以描述的所有关系(例如:
#Hoogle不是很有用,但是

因此,这是列表的一种特殊折叠形式,但它不适用于
长度列表
次,而适用于更少的一次

在名称上并不完全通用,但在签名上。也许坚持使用最通用的名称没有多大帮助。否则我们只是到处都有实体

定义如下:

isSortedBy函数在谓词为列表中所有相邻元素对返回True时返回True


也许:
所有相邻对(R\u 2,Xs)
。这听起来有点像是在循环构造之后,它将
相邻对
作为一些修饰符。

这是受我曾经实现的一个高阶函数习惯用法工具箱的启发。当时我发现角落案例令人痛苦,我今天仍然这样做:)同样,找到好名字总是一个问题

考虑元谓词
mapadj/4

mapadj(Relation_4,As,Bs,Cs) :-
   list_list_list_mapadj(As,Bs,Cs,Relation_4).

list_list_list_mapadj([],[],[],_).
list_list_list_mapadj([A|As],Bs,Cs,Relation_4) :-
   list_prev_list_list_mapadj(As,A,Bs,Cs,Relation_4).

list_prev_list_list_mapadj([],_,[],[],_).
list_prev_list_list_mapadj([A1|As],A0,[B|Bs],[C|Cs],Relation_4) :-
   call(Relation_4,A0,A1,B,C),
   list_prev_list_list_mapadj(As,A1,Bs,Cs,Relation_4).
foldadjl(Relation_4,Xs) -->
   list_foldadjl(Xs,Relation_4).

list_foldadjl([],_) -->
   [].
list_foldadjl([X|Xs],Relation_4) -->
   list_prev_foldadjl(Xs,X,Relation_4).

list_prev_foldadjl([],_,_) -->
   [].
list_prev_foldadjl([X1|Xs],X0,Relation_4) -->
   call(Relation_4,X0,X1),
   list_prev_foldadjl(Xs,X1,Relation_4).
tpartition(P_2,List,Ts,Fs) :- tpartition_ts_fs_(List,Ts,Fs,P_2).

tpartition_ts_fs_([],[],[],_).
tpartition_ts_fs_([X|Xs0],Ts,Fs,P_2) :-
   if_(call(P_2,X), (Ts = [X|Ts0], Fs = Fs0),
                    (Ts = Ts0,     Fs = [X|Fs0])),
   tpartition_ts_fs_(Xs0,Ts0,Fs0,P_2).
样本用途:

z_z_sum_product(X,Y,Sum,Product) :-
   Sum     #= X + Y,
   Product #= X * Y.

:- mapadj(z_z_sum_product,[],       [],     []).
:- mapadj(z_z_sum_product,[1],      [],     []).

:- mapadj(z_z_sum_product,[1,2],    [3],    [2]).
:- mapadj(z_z_sum_product,[1,2,3],  [3,5],  [2,6]).
:- mapadj(z_z_sum_product,[1,2,3,4],[3,5,7],[2,6,12]).
我意识到角落案例中的裂痕
As=[]
As=[[\u]
,但我仍然觉得这与“所有相邻列表项”一样接近

此外,所有这些都可以轻松扩展:

  • 下至
    mapadj/2
    (类似于
    chain/2
    ,使用单例列表进行类型检查除外)
  • 横向,带有附加状态参数,至
    foldadjl/n
    scanajl/n
关于名称:IMO的
l
/
r
后缀必须与
fold
/
scan
一起使用,而与
map
一起使用则不需要


编辑2015-04-26 下面是前面提到的
foldadjl/4

mapadj(Relation_4,As,Bs,Cs) :-
   list_list_list_mapadj(As,Bs,Cs,Relation_4).

list_list_list_mapadj([],[],[],_).
list_list_list_mapadj([A|As],Bs,Cs,Relation_4) :-
   list_prev_list_list_mapadj(As,A,Bs,Cs,Relation_4).

list_prev_list_list_mapadj([],_,[],[],_).
list_prev_list_list_mapadj([A1|As],A0,[B|Bs],[C|Cs],Relation_4) :-
   call(Relation_4,A0,A1,B,C),
   list_prev_list_list_mapadj(As,A1,Bs,Cs,Relation_4).
foldadjl(Relation_4,Xs) -->
   list_foldadjl(Xs,Relation_4).

list_foldadjl([],_) -->
   [].
list_foldadjl([X|Xs],Relation_4) -->
   list_prev_foldadjl(Xs,X,Relation_4).

list_prev_foldadjl([],_,_) -->
   [].
list_prev_foldadjl([X1|Xs],X0,Relation_4) -->
   call(Relation_4,X0,X1),
   list_prev_foldadjl(Xs,X1,Relation_4).
tpartition(P_2,List,Ts,Fs) :- tpartition_ts_fs_(List,Ts,Fs,P_2).

tpartition_ts_fs_([],[],[],_).
tpartition_ts_fs_([X|Xs0],Ts,Fs,P_2) :-
   if_(call(P_2,X), (Ts = [X|Ts0], Fs = Fs0),
                    (Ts = Ts0,     Fs = [X|Fs0])),
   tpartition_ts_fs_(Xs0,Ts0,Fs0,P_2).

编辑2015-04-27 下面是基于
如果/3
是在 关于物化

split_if_adj(P_3,As,Bss) :- splitlistIfAdj(P_3,As,Bss).

splitlistIfAdj(P_3,As,Bss) :- 
   list_split_(As,Bss,P_3).

list_split_([],[],_).
list_split_([X0|Xs],     [Cs|Bss],P_3) :-
   list_prev_split_(Xs,X0,Cs,Bss, P_3).

list_prev_split_([],     X, [X],[],_).
list_prev_split_([X1|Xs],X0,[X0|Cs],Bss,P_3) :-
   if_(call(P_3,X0,X1), 
       (Cs = [],  Bss = [Cs0|Bss0]),
       (Cs = Cs0, Bss = Bss0)),
   list_prev_split_(Xs,X1,Cs0,Bss0,P_3).
要在使用中显示它,让我们定义
dif/3
的方式与
(=)/3
完全相同,但具有翻转的真值:

dif(X, Y, R) :- X == Y,    !, R = false.
dif(X, Y, R) :- ?=(X, Y),  !, R = true. % syntactically different
dif(X, Y, R) :- X \= Y,    !, R = true. % semantically different
dif(X, Y, R) :- R == false, !, X = Y.
dif(X, X, false).
dif(X, Y, true) :-
   dif(X, Y).
现在我们将它们串联使用:

?- splitlistIfAdj(dif,[1,2,2,3,3,3,4,4,4,4],Pss).
Pss = [[1],[2,2],[3,3,3],[4,4,4,4]].      % succeeds deterministically
如果我们概括一些列表项呢?我们是否有多个正确的待定目标

首先,一个小例子:

?- splitlistIfAdj(dif,[1,X,2],Pss).
X = 1,             Pss = [[1,1],[2]]  ;
X = 2,             Pss = [[1],[2,2]]  ;
dif(X,1),dif(X,2), Pss = [[1],[X],[2]].
一个更大的例子涉及两个变量
X
Y

?- splitlistIfAdj(dif,[1,2,2,X,3,3,Y,4,4,4],Pss).
X = 2,             Y = 3,             Pss = [[1],[2,2,2],[3,3,3],[4,4,4]]    ;
X = 2,             Y = 4,             Pss = [[1],[2,2,2],[3,3],[4,4,4,4]]    ;
X = 2,             dif(Y,3),dif(Y,4), Pss = [[1],[2,2,2],[3,3],[Y],[4,4,4]]  ;
X = Y,             Y = 3,             Pss = [[1],[2,2],[3,3,3,3],[4,4,4]]    ;
X = 3,             Y = 4,             Pss = [[1],[2,2],[3,3,3],[4,4,4,4]]    ;
X = 3,             dif(Y,3),dif(Y,4), Pss = [[1],[2,2],[3,3,3],[Y],[4,4,4]]  ;
dif(X,2),dif(X,3), Y = 3,             Pss = [[1],[2,2],[X],[3,3,3],[4,4,4]]  ;
dif(X,2),dif(X,3), Y = 4,             Pss = [[1],[2,2],[X],[3,3],[4,4,4,4]]  ;
dif(X,2),dif(X,3), dif(Y,3),dif(Y,4), Pss = [[1],[2,2],[X],[3,3],[Y],[4,4,4]].

编辑2015-05-05 下面是
t部分/4

mapadj(Relation_4,As,Bs,Cs) :-
   list_list_list_mapadj(As,Bs,Cs,Relation_4).

list_list_list_mapadj([],[],[],_).
list_list_list_mapadj([A|As],Bs,Cs,Relation_4) :-
   list_prev_list_list_mapadj(As,A,Bs,Cs,Relation_4).

list_prev_list_list_mapadj([],_,[],[],_).
list_prev_list_list_mapadj([A1|As],A0,[B|Bs],[C|Cs],Relation_4) :-
   call(Relation_4,A0,A1,B,C),
   list_prev_list_list_mapadj(As,A1,Bs,Cs,Relation_4).
foldadjl(Relation_4,Xs) -->
   list_foldadjl(Xs,Relation_4).

list_foldadjl([],_) -->
   [].
list_foldadjl([X|Xs],Relation_4) -->
   list_prev_foldadjl(Xs,X,Relation_4).

list_prev_foldadjl([],_,_) -->
   [].
list_prev_foldadjl([X1|Xs],X0,Relation_4) -->
   call(Relation_4,X0,X1),
   list_prev_foldadjl(Xs,X1,Relation_4).
tpartition(P_2,List,Ts,Fs) :- tpartition_ts_fs_(List,Ts,Fs,P_2).

tpartition_ts_fs_([],[],[],_).
tpartition_ts_fs_([X|Xs0],Ts,Fs,P_2) :-
   if_(call(P_2,X), (Ts = [X|Ts0], Fs = Fs0),
                    (Ts = Ts0,     Fs = [X|Fs0])),
   tpartition_ts_fs_(Xs0,Ts0,Fs0,P_2).
样本使用:

?- tpartition(=(0), [1,2,3,4,0,1,2,3,0,0,1], Ts, Fs).
Ts = [0, 0, 0],
Fs = [1, 2, 3, 4, 1, 2, 3, 1].
:- use_module(library(clpfd)).
:- use_module(library(lambda)).

?- Ls = [0,_,_,_,_,_], forallAdj(\X0^X1^(X0 + 1 #= X1), Ls).
Ls = [0, 1, 2, 3, 4, 5].

编辑2015-05-15 不停地。。。下面是
拆分列表if/3

split_if(P_2,As,Bss) :- splitlistIf(P_2,As,Bss).

splitlistIf(P_2,As,Bss) :-
   list_pred_split(As,P_2,Bss).

list_pred_split([],_,[]).
list_pred_split([X|Xs],P_2,Bss) :-
   if_(call(P_2,X), list_pred_split(Xs,P_2,Bss),
                    (Bss = [[X|Ys]|Bss0], list_pred_open_split(Xs,P_2,Ys,Bss0))).

list_pred_open_split([],_,[],[]).
list_pred_open_split([X|Xs],P_2,Ys,Bss) :-
   if_(call(P_2,X), (Ys = [],      list_pred_split(Xs,P_2,Bss)),
                    (Ys = [X|Ys0], list_pred_open_split(Xs,P_2,Ys0,Bss))).
让我们使用它:

?- splitlistIf(=(x),[x,1,2,x,1,2,3,x,1,4,x,x,x,x,1,x,2,x,x,1],Xs).
Xs = [[1, 2], [1, 2, 3], [1, 4], [1], [2], [1]].

与前面的回答中给出的
mapadj/4
完全相同也许这个名字更好。

forallAdj(P_2,Xs) :-
   list_forallAdj(Xs,P_2).

list_forallAdj([],_).
list_forallAdj([X|Xs],P_2) :-
   list_forallAdj_prev(Xs,P_2,X).

list_forallAdj_prev([],_,_).
list_forallAdj_prev([X1|Xs],P_2,X0) :-
   call(P_2,X0,X1),
   list_forallAdj_prev(Xs,P_2,X1).
样本使用:

?- tpartition(=(0), [1,2,3,4,0,1,2,3,0,0,1], Ts, Fs).
Ts = [0, 0, 0],
Fs = [1, 2, 3, 4, 1, 2, 3, 1].
:- use_module(library(clpfd)).
:- use_module(library(lambda)).

?- Ls = [0,_,_,_,_,_], forallAdj(\X0^X1^(X0 + 1 #= X1), Ls).
Ls = [0, 1, 2, 3, 4, 5].
这会把我们带到哪里

  • forallAdj
    =>
    existAdj
  • 可能是索引为(
    forallAdjI
    existAdjI
    )的变体,如
  • findfirstAdj
    /
    pickfirstAdj
    也类似于F#
    find
    /
    pick

在给定的限制条件下,谓词应尽可能通用。它的名称应该尽可能具体,同时仍然包含所有用例
FoldCompl
朝着正确的方向前进(这也是字面意思)
foldadjl
…?非常感谢这个有用的元谓词列表,+1!对于这个具体的问题,我只搜索一个名字,所以我想你建议
mapadj/2
?这肯定会奏效。我看到两个仍然悬而未决的问题:(a)
mapadj/2
对“排序”以外的任何关系有用吗?(b)
mapadj/2
没有命名实际出现的结构,如
connex/2
,这在CLP(FD)约束的上下文中很有意义,因此从这个意义上讲,谓词(name)太笼统了?对许多功能的需求似乎非常特别——只是存在一些静态成员。因此,静态成员似乎有一个全局语义范围。我理解得对吗?我希望我们可以在类型类上有一些东西——至少在概念层面上。s(X)!对于部分目标(
relationship_2
)有很好的命名约定!