Prolog ile ilgili bir sorunu çözmek için, herhangi bir programlama dilinde olduğu gibi, ister açıklayıcı ister zorunlu olsun, çözümün ve girdinin temsilini düşünmelisiniz.
Bu bir programlama sorusu olduğundan, programcıların programlama sorunlarını çözdüğü StackOverflow.com'da popüler olurdu. Burada daha bilimsel olmaya çalışacağım.
OP'deki problemi çözmek için, girdide belirtilen bağımlılıklar tarafından tanımlanan ilişki tersine çevrilmelidir. formunun cümleleri kolayca tersine çevrilebilir. Maddeleri bir T T , e n d ( A D ) ∧ bir T T , e n dAttend(X)→Attend(Y)∧Attend(Z) gibiA t t e n d( A D ) ∧ A t t e n d( B M) → A t t e n d( D D )
Daisy Dodderidge Albus Dumbledore ve Burdock Muldoon gelse geleceğini söyledi
tedavisi daha zordur.
Prolog ile ilk basit yaklaşım, ilişkinin tamamen tersine çevrilmesini önlemek ve bunun yerine hedefe yönelik olmaktır.
Konuk listesinde bir sipariş olduğunu varsayalım ve bir kural kullanın
⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪A ( X) ∧ A ( Y)A ( W)A ( W)XY→ A ( Z) ,→ A ( X) ,→ A ( Y) ,< Z,< Z⎫⎭⎬⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⊢A ( W) → A ( Z)
( Kısa tutmak için A t t e n d ( X ) yerine kullanıyoruz )A ( X)A t t e n d( X)
Bu kuralın uygulanması kolaydır.
Oldukça naif bir yaklaşım
Okunabilirlik follows
için bir girdi olarak verilen ilişki ve brings
bunun tersi olsun.
Sonra giriş tarafından verilir
follows(bm,[ad]).
follows(cp,[ad]).
follows(ad,[cp]).
follows(dd,[cp]).
follows(ad,[ec]).
follows(bm,[ec]).
follows(cp,[ec]).
follows(cp,[fa]).
follows(dd,[fa]).
follows(bm,[cp,dd]).
follows(ec,[cp,dd]).
follows(fa,[cp,dd]).
follows(dd,[ad,bm]).
Ve brings
aşağıdaki gibi tanımlanabilir:
brings(X,S):-brings(X,S,[]).
brings(_X,[],_S).
brings(X,[X|L],S):-brings(X,L,[X|S]).
brings(X,[Y|L],S):-follows(Y,[X]),brings(X,L,[Y|S]).
brings(X,[Y|L],S):-follows(Y,[A,B]),
member(A,S),member(B,S),brings(X,L,[Y|S]).
brings/3(X,L,S)
X
Eğer tanımlarsak
partymaker(X):-Guests=[ad,bm,cp,dd,ec,fa],member(X,Guests),brings(X,Guests).
Aşağıdaki benzersiz çözümleri elde ediyoruz:
[ad,ec]
Bu tam liste değildir, çünkü cümlenin alfabetik sıralaması altında
follows(bm,[cp,dd]).
çalışmıyor.
Orijinal bulmacanın oldukça karmaşık bir çözümü
Sorunu tamamen çözmek için, sistemin arama ağacına sonsuz döngüler getirmeden daha sonraki konuklar için katılımı kanıtlamaya çalışmasına izin vermelisiniz. Bu hedefe ulaşmak için birçok yol vardır. Her birinin avantajı ve dejavantajı var.
Bunun bir yolu brings/2
aşağıdaki gibi yeniden tanımlamaktır :
brings(X,S):-brings(X,S,[],[]).
% brings(X,RemainsToBring,AlreadyTaken,AlreadyTried).
%
% Problem solved
brings(_X,[],_S,_N).
% Self
brings(X,[X|L],S,N):-brings(X,L,[X|S],N).
% Follower
brings(X,[Y|L],S,N):-follows(Y,[X]),brings(X,L,[Y|S],N).
% Y is not a follower, but X can bring 2
brings(X,[Y|L],S,N):- \+member(Y,N),\+follows(Y,[X]),
follows(Y,[A,B]),
try_bring(X,A,L,S,[Y|N]),
try_bring(X,B,L,S,[Y|N]),brings(X,L,[Y|S],N).
% Y is not a follower, but X can bring 1
brings(X,[Y|L],S,N):- \+member(Y,N),\+follows(Y,[X]),\+follows(Y,[_A,_B]),
follows(Y,[C]),
try_bring(X,C,L,S,[Y|N]),brings(X,L,[Y|S],N).
try_bring(_X,A,_L,S,_N):-member(A,S).
try_bring(X,A,L,S,N):- \+member(A,S),sort([A|L],Y),brings(X,Y,S,N).
İçindeki son argüman, brings/4
sonsuz bir döngüden kaçınmak için gereklidir try_bring
.
Bu şu cevapları verir: Albus, Carlotta, Elfrida ve Falco. Ancak bu çözüm en etkili çözüm değildir, çünkü bazen önlenebilir, bazen önlenebilir.
Genel bir çözüm
Orijinal soruya Üçüncü Uluslararası NoCOUG SQL ve NoSQL Mücadelesi bağlantısının eklenmesinden sonra, peşinde olduğumuz şeyin, geçiş ilişkisinin tanımlandığı konuk grubunun alt kümelerinde genel bir erişilebilirlik denetleyicisi olduğu ortaya çıktı. kuralın uygulanması için kurallar verilir r ( X, S) : V→ V' korumalı bir komuttur:
Eğer S⊆ V sonra V'= V∪ { X}.
Minimum alt kümelerle ilgileniyoruz V öyle ki bütün set U misafirlerden V sonlu kural uygulamaları dizisinden sonra.
add_element(X,V,U):- ( var(V) -> % set difference that works in both modes
member(X,U),subtract(U,[X],V);
\+member(X,V),sort([X|V],U) ).
support(V,U):- guests(G), % rule application
member(X,G),
add_element(X,V,U),
follows(X,S),
subset(S,V).
set_support(U,V):- support(V1,U), % sort of a minimal set
( support(_V2,V1) ->
set_support(V1,V) ;
V = V1).
is_duplicate(X,[Y|L]):- ( subset(Y,X) ; is_duplicate(X,L) ).
% purging solutions that are not truly minimal
minimal_support(U,L):-minimal_support(U,[],L).
minimal_support([],L,L).
minimal_support([X|L],L1,L2):-( append(L,L1,U),is_duplicate(X,U) ->
minimal_support(L,L1,L2);
minimal_support(L,[X|L1],L2) ).
solution(L):- guests(G),setof(X,set_support(G,X),S),
minimal_support(S,L).
Şimdi örneğin 2 numaralı veri kümesi şu şekilde verilirse
follows(fa,[dd,ec]).
follows(cp,[ad,bm]).
guests([ad,bm,cp,dd,ec,fa]).
L = [[ad, bm, dd, ec]] cevabını alıyoruz. Bu, Carlotte ve Falco dışındaki tüm misafirlerin davet edilmesi gerektiği anlamına gelir.
Bu çözümün verdiği cevaplar, daha fazla çözümün üretildiği veri seti # 6 dışında, Wicked Witch makalesinde verilen çözümleri eşleştirdi. Bu doğru çözüm gibi görünüyor.
Son olarak, Prolog'un bu tür problemler için özellikle uygun olan CLP (FD) kütüphanesinden bahsetmeliyim.
attend(BM) :- attend(AD).
tam olarak aynıdırattend(X) :- attend(Y).