Prolog 组合纯谓词
我试图结合前面堆栈溢出问题中的一些纯谓词来生成我自己的谓词 我想给出一个c的列表(与它们相关联的事实-‘at’)和一个‘feature’术语,它有一个运算符和一个‘at’的阈值。我想对c的列表进行分区,如果c没有“feature”中相应的“at”,它将进入假分区,否则操作员将测试该“c”的“at”,并适当地拆分c 例如:Prolog 组合纯谓词,prolog,logical-purity,Prolog,Logical Purity,我试图结合前面堆栈溢出问题中的一些纯谓词来生成我自己的谓词 我想给出一个c的列表(与它们相关联的事实-‘at’)和一个‘feature’术语,它有一个运算符和一个‘at’的阈值。我想对c的列表进行分区,如果c没有“feature”中相应的“at”,它将进入假分区,否则操作员将测试该“c”的“at”,并适当地拆分c 例如: ?-cpgpartition_ts_fs_feature([c1,c2,c3],Ts,Fs,feature(at2,_,>=,10)). 应导致: Ts = [c3],
?-cpgpartition_ts_fs_feature([c1,c2,c3],Ts,Fs,feature(at2,_,>=,10)).
应导致:
Ts = [c3], %c3 has an at2 >= 10
Fs = [c1,c2]. %c1 has at2 <10 and c2 does not have an at2
有趣的是,如果clist的顺序不同,结果也会改变
?- cpgpartition_ts_fs_feature([c3,c1,c2],Ts,Fs,feature(at2,_,>=,10)).
Ts = [c3|_12950],
Fs = [c1, c2] ;
Ts = [c3|_12950],
Fs = [c1, c2] ;
Fs = [c3, c1, c2] ;
Fs = [c3, c1, c2].
我认为这是因为下面的查询返回的结果带有dif/2
约束,这些约束似乎不适合我正在尝试做的事情,我只想要具体的解决方案
?- cpg_ats_i(C,Ats), if_(memberd_t(attribute(at2,AtValue),Ats),Q=true,Q=false).
C = c1,
Ats = [attribute(at1, 50), attribute(at2, 3)],
AtValue = 3,
Q = true ;
C = c1,
Ats = [attribute(at1, 50), attribute(at2, 3)],
Q = false,
dif(AtValue, 3) ;
C = c2,
Ats = [attribute(at1, 2)],
Q = false ;
C = c3,
Ats = [attribute(at2, 10), attribute(at3, 4), attribute(at4, 8)],
AtValue = 10,
Q = true ;
C = c3,
Ats = [attribute(at2, 10), attribute(at3, 4), attribute(at4, 8)],
Q = false,
dif(AtValue, 10).
另外,这段代码的目的是在一大组数据上运行,c的列表长度将达到数十万,每个c可能有50k的ats,我如何计算内存需求?使用不纯谓词的另一种方法可能占用更少的内存吗 正如您所提到的,问题在于以下定义中的dif(X,Y)行:
=(X, Y, T) :-
( X == Y -> T = true
; X \= Y -> T = false
; T = true, X = Y
; T = false,
dif(X, Y) % ISO extension
% throw(error(instantiation_error,_)) % ISO strict
).
这是因为如果你尝试:
memberd_t(attribute(at2,X),[attribute(at1,0.5),attribute(at2,0.03)],T).
X = 0.03,
T = true ;
T = false,
dif(X, 0.03).
这里给出解决方案的选择点:T=false,dif(X,0.03)。
将导致执行以下部分的Fs=[X | Fs0]
:
if_(memberd_t(attribute(At,AtValue3),AtList),
(
if_(call(Test), (Ts=[X|Ts0],Fs=Fs0),
( Ts =Ts0,Fs=[X|Fs0]))
)
,Fs=[X|Fs0]),
此外,这也是不正确的响应,因为如果在Atlist
中有属性(at2,0.03),您希望memberd\u t
返回X=0.03,t=true
,这将触发的,然后的部分if\u0/code>(并且没有其他t=false的解决方案会导致其他选择点执行Else\u 0部分)
因此您可以删除=/3
的T=false,dif(X,Y)
,现在让我们试试:
?- cpgpartition_ts_fs_feature([c1,c2,c3],Ts,Fs,feature(at2,_,>=,10)).
Fs = [c1, c2].
很好,但是Ts在哪里
所以还有另一个bug:
如上所述,它对Fs=[c1,c2]
和每一个Ts都成功。这是因为执行满足Fs
列表的if\u3
的Else\u 0
部分,您不限制Ts
列表,只需将其保留为Ts
,然后调用cpgpartition\u Ts\u功能(Xs0,Ts0,Fs0,feature)
与另一个独立于Ts的Ts0
列表。因此添加:
if_(memberd_t(attribute(At,AtValue3),AtList),
(
if_(call(Test), (Ts=[X|Ts0],Fs=Fs0), (Ts =Ts0,Fs=[X|Fs0]))
)
,(Fs=[X|Fs0], Ts = Ts0 )),
^^^^^^^^
here added
最后,根据@false的建议,我最好将Test=..[Op2,AtValue3,FValue],…,call(Test)
替换为call(Op2,AtValue3,FValue)
,因为call/N
是ISO的一部分,它适合原始的Mycroft-O'Keefe类型系统
现在让我们再试一次:
?- cpgpartition_ts_fs_feature([c1,c2,c3],Ts,Fs,feature(at2,_,>=,10)).
Ts = [c3],
Fs = [c1, c2].
似乎是正确的和决定性的:)
至于你问题的内存部分,我不太确定,但我更喜欢确定性谓词,它们不会为内存效率留下选择点。使用纯谓词将使您的编程更具关联性,并具有更好的行为,但我不确定如果\u3
包含许多调用,那么它的内存效率是否如此高,但我不确定是否其他人可以更清楚地回答这一部分。多亏了编码器的回答,我想出了:
cpgpartition_ts_fs_feature([],[],[],_).
cpgpartition_ts_fs_feature([X|Xs0],Ts,Fs,feature(At,_,Op,FValue)):-
cpg_ats_i(X,AtList),
atom_concat(#,Op,Op2), %make clpfd operator
maplist(atterm_atname,AtList,Ats),
if_(memberd_t(At,Ats),
(
memberchk(attribute(At,AtValue3),AtList),
if_(call(Op2,AtValue3,FValue), (Ts=[X|Ts0],Fs=Fs0),
( Ts =Ts0,Fs=[X|Fs0]))
),
(Fs=[X|Fs0],Ts=Ts0)
),
cpgpartition_ts_fs_feature(Xs0,Ts0,Fs0,feature(At,_,Op,FValue)).
atterm_atname(attribute(At,_),At).
这使我能够在不改变=/3
的定义的情况下得到相同的结果,当前建议的if_uu3;/3实现是错误的,因为
它把一个选择点放在物化上,而不是放在
如果不是这样的话。以下是一个示例缺陷:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)
?- call(','(X=Y,2=3),B).
X = Y,
B = false ; %%% a bloody choice point %%%
B = false,
dif(X, Y).
在这里,我们看到一个更好的智能连接
例如,SWI Prolog中CLP(FD)中的#/\。别无选择
创建点时:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)
?- X #= Y #/\ 2 #= 3 #<==> B.
B = 0,
X in inf..sup,
Y in inf..sup.
想法是不要将任何选择点放入具体化/2,
尽量避免它们。当前(=)/3创建
一个选择点,组合时不好
条件。也许我们也可以在同样的条件下安排
在代码中的不同位置,共享相同的布尔值
指标变量。处理它…乍一看,将Test=…[Op2,AtValue3,FValue],…,调用(Test)
替换为call(Op2,AtValue3,FValue)
Done。但这似乎并没有什么不同…很棒的地方!谢谢:)
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)
?- call(','(X=Y,2=3),B).
X = Y,
B = false ; %%% a bloody choice point %%%
B = false,
dif(X, Y).
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)
?- X #= Y #/\ 2 #= 3 #<==> B.
B = 0,
X in inf..sup,
Y in inf..sup.
if(Cond, Then, Else) :-
reify(Cond, Bool),
thenelse(Bool, Then, Else)
thenelse(1, Then, _) :- Then.
thenelse(0, _, Else) :- Else.