क्या प्रोलॉग के साथ बाधा संतुष्टि समस्याओं को हल किया जा सकता है?


18

क्या "पार्टी अटेंडेंस" प्रकार की समस्याएं प्रोलॉग में हल करने योग्य हैं? उदाहरण के लिए:

बर्डॉक मुलदून और कार्लोटा पिंकस्टोन दोनों ने कहा कि अगर अल्बस डंबलडोर आए तो वे आएंगे। एल्बस डंबलडोर और डेज़ी डोडरिज ने कहा कि अगर कार्लोटा पिंकस्टोन आए तो वे आएंगे। एल्बस डंबलडोर, बर्डॉक मुल्दून, और कार्लोट्टा पिंकस्टोन सभी ने कहा कि यदि एल्फ्रिडा क्लैग आए तो वे आएंगे। कार्लोट्टा पिंकस्टोन और डेज़ी डोडरिज ने कहा कि यदि फाल्को ऐसालोन आए तो वे आएंगे। बर्डॉक मुलदून, एल्फ्रिडा क्लैग, और फाल्को ऐसालोन सभी ने कहा कि अगर कार्लोटा पिंकस्टोन और डेज़ी डोडरिज दोनों आए तो वे आएंगे। डेज़ी डोडरिज ने कहा कि अगर अल्बस डंबलडोर और बर्डॉक मुलदून दोनों आए तो वह आएगी। यह सुनिश्चित करने के लिए कि उसे सभी आमंत्रितों को उपस्थित होने के लिए पार्टी में शामिल होने के लिए किससे मनाने की आवश्यकता है?

मैंने इसे GNU प्रोलॉग में व्यक्त करने की कोशिश की है:

attend(BM) :- attend(AD).
attend(CP) :- attend(AD).
attend(AD) :- attend(CP).
attend(DD) :- attend(CP). 
attend(AD) :- attend(EC).
attend(BM) :- attend(EC).
attend(CP) :- attend(EC). 
attend(CP) :- attend(FA).
attend(DD) :- attend(FA).
attend(BM) :- attend(CP),attend(DD).
attend(EC) :- attend(CP),attend(DD).
attend(FA) :- attend(CP),attend(DD).
attend(DD) :- attend(AD),attend(BM).

attend(FA). /* try different seed invitees in order to see if all would attend*/

/* input:
write('invited:'),nl,
  attend(X),write(X),nl,
  fail.*/

मैं स्टैक ओवरफ़्लो (कोई सज़ा नहीं) का अनुभव कर रहा हूं, और प्रोलॉग मूल्यांकन का कोई ज्ञान नहीं है, यही कारण है कि मैं पूछ रहा हूं।

सामान्यतया, इस समस्या को बूलियन CNF संतुष्टि सूत्र (6 बूलियन चर के साथ) में डाला जा सकता है। इसलिए, क्या प्रोलॉग परिप्रेक्ष्य में कोई योग्यता है?


2
मुझे लगता है कि आपकी समस्या यह है कि अपरकेस पहचानकर्ता चर हैं, इसलिए attend(BM) :- attend(AD).बिल्कुल वैसा ही हैattend(X) :- attend(Y).
svick

छोटे अक्षरों ( ideone.com/w622Z ) के साथ अभी भी एक ही परिणाम की कोशिश की।
तेगिरी नेनाशी

मैंने स्पष्ट रूप से बहुत अधिक समय में कोई बुध / प्रस्तावना नहीं किया है, निश्चित रूप से svick की बात सही है, और आपका पहला कार्यक्रम मोटे तौर पर "किसी व्यक्ति को भर्ती कराया जाता है, तो यह कहने से मेल खाता है"। चर को ठोस शब्दों के साथ बदलने के बाद, आप तब मेरे उत्तर में बताई गई समस्या में भाग जाते हैं।
बेन

सरल उत्तर है, "हां," क्योंकि प्रोलॉग एक ट्यूरिंग-पूर्ण भाषा है।
डेविड रिचरबी

जवाबों:


13

प्रोलॉग के साथ एक समस्या को हल करने के लिए, किसी भी प्रोग्रामिंग भाषा के साथ, यह घोषणात्मक या अनिवार्य है, आपको समाधान और इनपुट के प्रतिनिधित्व के बारे में सोचना होगा।

चूँकि यह एक प्रोग्रामिंग प्रश्न है, यह StackOverflow.com पर लोकप्रिय होगा जहाँ प्रोग्रामर प्रोग्रामिंग की समस्याओं को हल करते हैं। यहाँ मैं और अधिक वैज्ञानिक बनने का प्रयास करूँगा।

ओपी में समस्या को हल करने के लिए इनपुट में निर्भरताओं द्वारा परिभाषित संबंध को उल्टा करना पड़ता है। फार्म के क्लाज उल्टा करने के लिए आसान है। खंड एक टी टी एन डी ( डी ) एक टी टी एन डी (टीटीn(एक्स)टीटीn(Y)टीटीn(जेड) जैसेटीटीn(डी)टीटीn(बी)टीटीn(डीडी)

डेज़ी डोडरिज ने कहा कि अगर अल्बस डंबलडोर और बर्डॉक मुलदून दोनों आए तो वह आएगी

इलाज करना ज्यादा मुश्किल है।

प्रोलॉग के साथ पहला सरल दृष्टिकोण संबंध के पूर्ण उलट से बचने और इसके बजाय निर्देशित लक्ष्य होना है।

मेहमानों की सूची पर एक आदेश मान लें और एक नियम का उपयोग करें

{(एक्स)(Y)(जेड),(डब्ल्यू)(एक्स),(डब्ल्यू)(Y),एक्स<जेड,Y<जेड}(डब्ल्यू)(जेड)

(हम का उपयोग के बजाय एक टी टी एन डी ( एक्स ) यह कम रखने के लिए)(एक्स)टीटीn(एक्स)

इस नियम को लागू करना आसान है।

बल्कि भोली दृष्टिकोण

पठनीयता के लिए followsएक इनपुट के रूप में दिए गए संबंध bringsहो , और इसके विपरीत हो।

फिर इनपुट के द्वारा दिया जाता है

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]).

और bringsनिम्नानुसार परिभाषित किया जा सकता है:

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)एक्स

अगर हम परिभाषित करते हैं

 partymaker(X):-Guests=[ad,bm,cp,dd,ec,fa],member(X,Guests),brings(X,Guests).

हम निम्नलिखित अद्वितीय समाधान प्राप्त करते हैं:

 [ad,ec]

यह पूरी सूची नहीं है, क्योंकि वर्णमाला के तहत खंड का आदेश दिया गया है

 follows(bm,[cp,dd]).

काम नहीं कर रहा।

मूल पहेली के बजाय एक शामिल समाधान

समस्या को पूरी तरह से हल करने के लिए आपको वास्तव में सिस्टम को बाद के मेहमानों के लिए उपस्थिति साबित करने की कोशिश करनी चाहिए ताकि खोज के पेड़ पर अनंत छोरों की शुरुआत न हो। इस लक्ष्य को पूरा करने के कई तरीके हैं। प्रत्येक के अपने फायदे और नुकसान है।

एक तरीका brings/2इस प्रकार परिभाषित करना है:

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

में brings/4एक अनंत लूप से बचने के लिए अंतिम तर्क आवश्यक है try_bring

यह निम्नलिखित उत्तर देता है: एल्बस, कार्लोटा, एल्फ्रिडा और फाल्को। हालांकि यह समाधान सबसे कुशल नहीं है क्योंकि बैकट्रैकिंग को पेश किया जाता है जहां इसे कभी-कभी टाला जा सकता है।

एक सामान्य उपाय

आर(एक्स,एस):वीवी'

एसवीवी'=वी{एक्स}

वीयूवी

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

अब अगर उदाहरण के लिए डाटासेट # 2 के रूप में दिया जाता है

follows(fa,[dd,ec]).
follows(cp,[ad,bm]).
guests([ad,bm,cp,dd,ec,fa]).

हमें उत्तर L = [[ad, bm, dd, ec]] मिलता है। जिसका अर्थ है कि सभी मेहमानों को लेकिन कारलोट और फाल्को को आमंत्रित किया जाना चाहिए।

इस समाधान ने मुझे जो जवाब दिए, वे दुष्ट चुड़ैल लेख में दिए गए डेटासेट # 6 के अपवाद के साथ दिए गए समाधान से मेल खाते हैं, जहां अधिक समाधान का उत्पादन किया गया था। यह सही समाधान प्रतीत होता है।

अंत में, मुझे Prolog की CLP (FD) लाइब्रेरी का उल्लेख करना चाहिए जो इस प्रकार की समस्याओं के लिए विशेष रूप से उपयुक्त है।


सही उत्तर में F (यानी A, C, E, F) भी शामिल है। आप या तो नियमों में टाइपो, या कार्यक्रम में अधिक गंभीर समस्या है।
तेगिरी नेनाशी


डेटासेट # 2 साइट से जुड़े लेख ideone.com/21AmX पर यह काम नहीं कर रहा है ...
तेगिरी नेनाशी

क्या आपका समाधान कई विकल्प (डेटासेट # 8) ideone.com/rBjXi
Tegiri Nenashi

@TegiriNenashi 6 "जुड़े हुए स्थल पर" धारणा नहीं है। मेरा समाधान and 2 और № 5 को संतुष्ट नहीं करता है। easy 5 को ठीक करना आसान लगता है: दो "% नहीं एक अनुयायी" नियमों को सामान्य करें। अगर यह तय हो गया है तो इसे डाटासेट # 8 के लिए पहला उत्तर मिलना चाहिए। जब तक धारणा assum 2 संतुष्ट है न तो उदाहरण का डेटासेट को सही तरीके से हल किया जा सकता है।
दिमित्री चुबरोव

10

जैसा कि स्विक द्वारा देखा गया है, ओपी में कोड के साथ पहला मुद्दा यह है कि अपर-केस अक्षरों से शुरू होने वाले नाम प्रोलॉग में चर हैं। तो admit(CP) :- admit(AD)इसके समतुल्य है attend(X) :- attend(Y), जिसके परिणामस्वरूप प्रोलॉग तुरंत एक अनंत लूप में प्रवेश करता है जो यह प्रदर्शित करने की कोशिश करता है कि attendकिस अवधि के लिए कुछ शब्द ढूंढकर attendरखता है।

हालाँकि, यदि आप का अर्थ है कि प्रारंभिक सेट का प्रत्येक सेट एक ठोस भिन्न शब्द है, तो आप अभी भी एक स्टैक ओवरफ़्लो में चलेंगे क्योंकि आपके पास साइकिल है, जैसे।

attend(cp) :- attend(ad).
attend(ad) :- attend(cp).

तो यह पता लगाने के लिए कि क्या attend(cp)प्रोलॉग यह निर्धारित करने की कोशिश करेगा कि क्या attend(ad)धारण करता है, जो कि यह जाँच करता है कि क्या attend(cp)धारण करता है, और इसी तरह जब तक स्टैक ओवरफ्लो न हो।

मेरा मानना ​​है कि वेनिला प्रोलॉग यह निर्धारित करने का कोई प्रयास करता है कि क्या इस तरह का एक चक्र है, और एक अनंत लूप में फंसने के बजाय एक या सच बनाने के अन्य तरीकों की जांच करें ।attend(cp)attend(ad)

प्रोलॉग के संस्करण हो सकते हैं या नहीं भी हो सकते हैं जो इस तरह की सुविधा का समर्थन करते हैं। मैं बुध के साथ अधिक परिचित हूं, और मुझे लगता है कि बुध की "न्यूनतम मॉडल सारणी" ठीक वही है जो आपको इस मामले के लिए चाहिए। मैंने वास्तव में इसका उपयोग कभी नहीं किया है, लेकिन मेरी समझ यह है कि यह अधिक-या-कम एक ऐसे शब्द की अनुमति देता है जो खुद को सच मानने की अनुमति देता है अगर कोई अनन्त लूप में पकड़े बिना इसे साबित करने का कोई अन्य तरीका है, या गलत है। बुध डॉक्स का प्रासंगिक अनुभाग देखें , और यदि आप कार्यान्वयन का वर्णन करने वाले पेपर में रुचि रखते हैं ।

पारा एक प्रवर्तित-शुद्धता तार्किक प्रोग्रामिंग भाषा है, जो प्रोलॉग लेकिन मजबूत प्रकार और मोड सिस्टम के समान सिंटैक्स के साथ है, और इसकी व्याख्या के बजाय संकलित है।

मैंने सिर्फ कागज़ से परिचय को दोबारा प्राप्त किया है (जो मैंने थोड़ी देर में पढ़ा नहीं है), और इसमें प्रोलॉग्स के कई संस्करणों में लागू किए जाने को शामिल करने का उल्लेख किया गया है, इसलिए यह हो सकता है कि आप टैबलिंग के लिए googling द्वारा आगे बढ़ सकते हैं प्रोलॉग में।


4

मैं सैट को हल करते हुए निम्नलिखित पेपर पर पाया गया:

सॉल्वर का एक कार्यान्वयन यहां पाया जा सकता है

कोड पर विवरण के लिए यह स्टैकओवरफ़्लो उत्तर देखें और इसका उपयोग कैसे करें।


0

लोअरकेस / अपरकेस मुद्दे को एक तरफ रखकर, क्लॉस में एक चक्र है:

attend(cp) :- attend(ad).
attend(ad) :- attend(cp).

इसलिए जब आप एक टॉप-डाउन दुभाषिया कहते हैं, तो यह लूप होगा। आपको उत्तर सेट प्रोग्रामिंग (एएसपी) के साथ अधिक भाग्य हो सकता है , जो नीचे काम करता है। यहां लाइब्रेरी ( न्यूनतम / एस्प ) के माध्यम से एक कोडिंग है :

:- use_module(library(minimal/asp)).

choose([admit(bm)]) <= posted(admit(ad)).
choose([admit(cp)]) <= posted(admit(ad)).
choose([admit(ad)]) <= posted(admit(cp)).
choose([admit(dd)]) <= posted(admit(cp)).
choose([admit(ad)]) <= posted(admit(ec)).
choose([admit(bm)]) <= posted(admit(ec)).
choose([admit(cp)]) <= posted(admit(ec)).
choose([admit(cp)]) <= posted(admit(fa)).
choose([admit(dd)]) <= posted(admit(fa)).
choose([admit(bm)]) <= posted(admit(cp)),posted(admit(dd)).
choose([admit(ec)]) <= posted(admit(cp)),posted(admit(dd)).
choose([admit(fa)]) <= posted(admit(cp)),posted(admit(dd)).
choose([admit(dd)]) <= posted(admit(ad)),posted(admit(bm)).

choose([admit(fa)]) <= posted(init).

यहाँ एक उदाहरण चलाया गया है:

Jekejeke Prolog 3, Runtime Library 1.3.8 (23 May 2019)

?- post(init), listing(admit/1).
admit(fa).
admit(cp).
admit(ad).
admit(bm).
admit(dd).
admit(ec).
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.