描述相对于关系sorting的整数序列的大多数一般的高阶约束
在CLP(FD)中,我们经常需要陈述:“这是一个整数和有限域variables的列表(有时: 严格地说 )是升序/降序。
是否有任何CLP(FD)系统为此任务提供一个通用(可参数化)的内置约束?
SWI-Prolog提供了一个叫做chain/2
的约束,与我正在寻找的相似。 然而,这个名字稍微有些特殊,不能包含约束可以描述的所有关系(例如: #<
不是一个偏序,但是在第二个chain/2
是可以接受的,导致序列被看作是一个整数集合 -math顺序理论中定义的一个链)。 因此,这个名字并没有完全描述约束实际实现的内容。
请给出关于通常的二进制CLP(FD)约束的最一般的定义 – 或者至less包含#<
, #>
, #=<
和#>=
– 的合适的子集, 包括根据代数结构约束定义。 强加的条件是约束描述了一个在文献中有一个真正的名字的实际math结构。
首先,请考虑使用SICStus Prolog或SWI:
:- use_module(library(clpfd)). connex(Relation_2, List) :- connex_relation(Relation_2), connex_(List, Relation_2). connex_relation(#=). connex_relation(#<). connex_relation(#=<). connex_relation(#>). connex_relation(#>=). connex_([], _). connex_([L|Ls], Relation_2) :- foldl(adjacent(Relation_2), Ls, L, _). adjacent(Relation_2, X, Prev, X) :- call(Relation_2, Prev, X).
示例:
?- connex(#<, [A,B,C]). A#=<B+-1, B#=<C+-1. ?- connex(#=, [A,B,C]). A = B, B = C, C in inf..sup. ?- maplist(connex(#<), [[A,B],[C,D]]). A#=<B+-1, C#=<D+-1.
请注意,甚至可以允许#\=
,因为这个关系仍然会描述一个在math顺序理论中已知的连接。 因此,对于通常的二进制CLP(FD)约束,上面的代码并不是最一般的。
Hoogle不是很有用,但是Hayoo是!
foldcmpl
所以这是一个列表的一种特殊的折叠forms,但是它不适用于length list
时间,但是一次不会。
isSortedBy
并不完全是一般的名字,而是签字。 也许坚持最普通的名字是没有帮助的。 否则,我们只是有实体吗?
定义如下:
如果谓词对列表中的所有相邻元素对返回true,则isSortedBy函数返回True。
也许: all_adjacent_pairs(R_2, Xs)
。 这听起来有点像一些修饰符一样有一个有adjacent_pair
的匹配的循环结构。
这是由我曾经实施过的function性高级成语的工具箱所启发的。 当时我发现angular落的情况下痛苦,我今天仍然做:)而且,find好名字总是一个问题…
考虑一下meta-predicate 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).
示例用途:
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]).
我知道在angular落案件中的裂痕As = []
和As = [_]
,但我仍然觉得这与“对于所有相邻列表项目”是一样的。
而且,所有这些都可以很容易地扩展:
- 到
mapadj/2
(类似于chain/2
,除了带单例列表的types检查) - 横向,带有一个额外的状态参数,
foldadjl/n
,scanadjl/n
关于名称:IMO l
/ r
后缀是需要fold
/ scan
,而不是与map
。
编辑2015-04-26
这里是前面提到的foldadjl/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).
编辑2015-04-27
这里是meta-predicate splitlistIfAdj/3
,它基于if_/3
,它是在上一个关于if_/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]].
涉及两个variablesX
和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
这里是tpartition/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].
编辑2015-05-15
在和上,…这是splitlistIf/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).
样品使用:
:- 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
)就像Collections.List模块(F#) -
findfirstAdj
/pickfirstAdj
也像F#find
/pick