2017-09-27 77 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定義。