2017-09-27 74 views
3

我想结合以前的堆栈溢出问题的一些纯谓词来做出我自己的谓词。结合纯谓词

我想给出一个c的列表(它们与它们有相关的事实 - 'at')和一个'特征'项,它有一个操作符和一个'at'的阈值。我想分割c的列表,如果c没有相应的'at',它就会进入假分区,否则运算符会测试'at'来得到'c',然后分割适当的。

例如:

?-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 

这是我的代码有:

:-use_module(library(clpfd)). 

cpgpartition_ts_fs_feature([],[],[],_). 
cpgpartition_ts_fs_feature([X|Xs0],Ts,Fs,Feature):- 
    Feature = feature(At,_,Op,FValue), 
    cpg_ats_i(X,AtList), 
    atom_concat(#,Op,Op2), %make clpfd operator 
    Test =..[Op2,AtValue3,FValue], 
    if_(memberd_t(attribute(At,AtValue3),AtList), 
     (
     if_(call(Test), (Ts=[X|Ts0],Fs=Fs0), 
     ( Ts =Ts0,Fs=[X|Fs0])) 
     ) 
     ,Fs=[X|Fs0]), 
    cpgpartition_ts_fs_feature(Xs0,Ts0,Fs0,Feature). 

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,_)) 
    ). 

bool01_t(1,true). 
bool01_t(0,false). 

=(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 
    ). 

#=<(X,Y,Truth) :- X #=< Y #<==> B, bool01_t(B,Truth). 

#<(X,Y,Truth) :- X #< Y #<==> B, bool01_t(B,Truth). 

#>(X,Y,Truth) :- X #> Y #<==> B, bool01_t(B,Truth). 

#>=(X,Y,Truth) :- X #>= Y #<==> B, bool01_t(B,Truth). 

list_memberd_t([] ,_,false). 
list_memberd_t([Y|Ys],X,Truth) :- 
    if_(X=Y, Truth=true, list_memberd_t(Ys,X,Truth)). 

list_memberd_truth(Xs,X,Truth) :- list_memberd_t(Xs,X,Truth). 

memberd_t(X,Xs,Truth) :- list_memberd_t(Xs,X,Truth). 

value_intvalue(attribute(_A,X),attribute(_A,Y)):- 
     AtValue2 is X *100, %Convert decimal number to integer. 
     Y is integer(AtValue2). 

cpg_ats_i(C,AtList):- 
     cpg_ats(C,Ats), 
     maplist(value_intvalue,Ats,AtList). 

cpg_ats(c1,[attribute(at1,0.5),attribute(at2,0.03)]). 
cpg_ats(c2,[attribute(at1,0.02)]). 
cpg_ats(c3,[attribute(at2,0.1),attribute(at3,0.04),attribute(at4,0.08)]). 

当试图测试查询我得到:

cpgpartition_ts_fs_feature([c1,c2,c3],Ts,Fs,feature(at2,_,>=,10)). 
Fs = [c1, c2] ; 
Fs = [c1, c2, c3] ; 
Fs = [c1, c2] ; 
Fs = [c1, c2, c3]. 

有趣的是,如果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可能有ATS的50K,我怎么能计算出所需的内存?而使用不纯谓词可能会减少内存的方法不同?

+1

乍一看,通过'call(Op2,AtValue3,FValue)' – false

+0

完成'Test = .. [Op2,AtValue3,FValue],...,call(Test)'。但它似乎没有区别... – user27815

回答

4

至于你提到的问题是在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_t返回X = 0.03, T = true这将触发部分if_/3(并且没有其他解决方案T = false将导致其他选择点执行Else_0部分)。

所以,你可以删除=/3T = false,dif(X, Y),现在让我们尝试:

?- cpgpartition_ts_fs_feature([c1,c2,c3],Ts,Fs,feature(at2,_,>=,10)). 
Fs = [c1, c2]. 

好,但哪里是TS?

那么还有另外一个错误:

上面说,它成功的Fs = [c1,c2]为每TS。这是因为执行Else_0部分if_/3履行Fs名单你不限制Ts名单只是离开Ts和稍后调用cpgpartition_ts_fs_feature(Xs0,Ts0,Fs0,Feature)与另一个Ts0列表独立的Ts。所以加:

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最好是由call(Op2,AtValue3,FValue)因为call/N是ISO的部分替代Test =..[Op2,AtValue3,FValue], ..., call(Test)和其装入原迈克罗夫特奥基夫类型的系统。

现在让我们再试一次:

?- cpgpartition_ts_fs_feature([c1,c2,c3],Ts,Fs,feature(at2,_,>=,10)). 
Ts = [c3], 
Fs = [c1, c2]. 

似乎是正确的和确定性:)!。

至于你的问题的记忆部分我不确定,但更喜欢确定性谓词,不留下选择点的记忆效率。使用纯谓词会让你的程序更具关联性,并且会有更好的行为,但我不确定if_/3是否具有如此高的内存效率,因为它包含很多调用,但我不确定也许其他人可以更清楚地回答这部分。

+0

很棒的地方!谢谢:) – user27815

+0

@ user27815,很高兴帮助! – coder

1

由于从编码器的答案,我想出了:

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定义。