2013-06-19 8 views
5

में लक्ष्यों के एक समूह को संतुष्ट करना प्रोलॉग में मैं अक्सर एक टेम्पलेट (चर युक्त संरचना) प्रदान करके एक समस्या हल करता हूं और फिर उस पर बाधाओं का एक सेट संतुष्ट करता हूं। एक तुच्छ उदाहरण हो सकता है:प्रोलॉग

go(T) :- 
    T = [_, _, _], 
    member(cat, T), 
    member(dog, T), 
    member(mouse, T). 

और व्यवहार में कमी के सेट किसी अन्य तरीके से उत्पन्न करने के बजाय है तय किया जा रहा है, और मैं एक पुनरावर्ती विधेय लिखने के बदले में प्रत्येक बाधा को संतुष्ट करने के लिए है:

go(T) :- 
    T = [_, _, _], 
    findall(A, animal(A), As), 
    % satisy member(A, T) for each A in As 
    fill_in_animals(T, As) 

fill_in_animals(T, []). 
fill_in_animals(T, [A|Rest]) :- 
    member(A, T), 
    fill_in_animals(T, Rest). 

ध्यान दें कि मेरा प्रश्न सूची से संबंधित बाधाओं के बारे में नहीं है, और यहां तक ​​कि बाधाओं के पैरामीटर को उपरोक्त उपयोग किए जाने वाले अपेक्षाकृत सरल सहायक अनुमान के लिए हमेशा एक सूची के रूप में आसानी से जेनरेट नहीं किया जा सकता है। अभ्यास में मुझे लगता है सहायक एक नहीं बल्कि कुरूप विधेय है कि मैं हर बार है, जो लिखना है:

  1. एक टेम्पलेट स्वीकार करता है, कई मापदंडों (और इसलिए उपयोगी मूल्यों के लिए खाके के चर बाइंडिंग के लिए) बाधा के लिए प्रयोग की जाने वाली, और एक चर जो यह इंगित करता है कि यह किस बाधा पर निर्भर है।
  2. इस पुनरावृत्ति में संतुष्ट करने के लिए एक बाधा उत्पन्न करता है, इसे टेम्पलेट पर लागू करता है।
  3. रिकर्सिव रूप से स्वयं को कॉल करता है ताकि शेष बाधाएं संतुष्ट हो सकें।

जो मैं खोज रहा हूं वह findall, आदि के साथ एक अनुमान है, जो लक्ष्य के एक सेट को पूरा करेगा, एक के बाद एक। कुछ ऐसा:

% satisfyall(:Goal) 
% backtracks on Goal but keeps all bindings from each fully satisfied goal. 

satisfyall((animal(A), member(A, T))) 

जो उत्तर मैं ढूंढ रहा हूं उसे इस फ़ॉर्म में नहीं होना चाहिए। वास्तव में एक लक्ष्य पर बैकट्रैकिंग और इसके परिणामस्वरूप बाइंडिंग के प्रत्येक सेट को बनाए रखने के बीच एक विरोधाभास हो सकता है।

मुझे आशा है कि मैंने अपनी समस्या समझाई है ताकि यह स्पष्ट रूप से स्पष्ट हो सके कि क्या मदद करेगा। (अगर मुझे नहीं पता है।) लंबे समय से चलने वाले प्रश्न के लिए अग्रिम क्षमा करें!

अद्यतन (2 साल बाद)

मैं इसे बाद में आज बाहर कोशिश करते हैं और मेरे सवाल का अद्यतन कर देंगे!

ध्यान दें कि मैंने कभी नहीं कहा था कि मैं उसी दिन प्रश्न को अपडेट करने के रूप में अपडेट करूंगा। ;-)

@CapelliC मुझे सही दिशा में चलाया गया है, और मैं एक पैटर्न जो बहुत अच्छी तरह से काम करने के लिए लगता है मिल गया है:

?- Gs = [member(red),member(blue)], T = [_,_], foreach(member(G, Gs), call(G, T)). 
T = [red, blue] ; 
T = [blue, red] ; 
+2

[lambda.pl] (http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl) मदद कर सकता है, लेकिन मुझे लगता है कि आप findall साथ जाना चाहिए/3 – CapelliC

+0

क्या कोई विशेष कारण है कि लैम्ब्डा एसडब्ल्यूआई के साथ वितरित नहीं किया गया है? मैं 'use_module (लाइब्रेरी (लैम्ब्डा)) 'करने में सक्षम होना पसंद करूंगा! –

+0

@DanielLyons: जब मैंने इस सवाल का जवाब देने की कोशिश की तो मुझे कुछ डाउनवोट मिला :) – CapelliC

उत्तर

1

आप निश्चित रूप से जानते हैं कि बैकट्रैकिंग को की आवश्यकता है ताकि काम में किए गए परिवर्तनों को पूर्ववत किया जा सके। यह प्रोलॉग एल्गोरिदम का मूल है, और प्रोलॉग पावर का स्रोत है।

यह भी एक कमजोर बिंदु है, जब यह अधिक सामान्य गणनाओं में आता है, जैसे आवश्यक साइड इफेक्ट्स, या लूप के साथ शामिल है।

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

खैर, अब, दर्शन दोषारोपण रोक, चलो देखते हैं कि क्या Prolog के गुरु हमारे पास उपलब्ध बना दिया है: SWI-Prolog पुस्तकालय (aggregate), जहां आप पाते हैं foreach प्रदान करता है, मुझे लगता है कि आप के बाद क्या कर रहे हैं की बहुत करता है:

?- foreach(animal(X), member(X,L)). 
L = [cat, dog, mouse|_G10698] . 

इस तरह के जटिल builtin अध्ययन आप अपने कार्यान्वयन (कंसोल से उपयोग ?- edit(foreach). स्रोत का निरीक्षण करने के लिए) के लिए कुछ विचार दे सकता है।

ध्यान दें कि यह जनरेटर और लक्ष्य को अलग करता है, जबकि आपके प्रश्न में वे निराशाजनक हैं। जेनरेटर भाग पर केवल बैकट्रैक करने में सक्षम होने के लिए की आवश्यकता है।

बीटीडब्ल्यू, दस्तावेज़ पृष्ठ में छोटे उदाहरण सूची को समझने का प्रयास करें। यह dif/2 द्वारा अत्यधिक जटिल है, लेकिन आपको वास्तव में बाइंडिंग के व्यवहार को समझने की आवश्यकता होगी ताकि आप अपने रिकर्सिव भविष्यवाणियों को सामान्यीकृत कर सकें।

HTH

+0

हे, देर से उत्तर के लिए खेद है। मुझे लगता है कि आपने मुझे सही रास्ते पर रखा है। – Edmund

3

स्थिति है कि विचाराधीन वर्णन हस्ताक्षर से थोड़ा अलग है आपके द्वारा दिए गए satisfyall/1 की भविष्यवाणी करें। fill_in_animals उदाहरण में शामिल कोई बैकट्रैकिंग नहीं है, कम से कम go/1 से बाहर होने वाले चर के संबंध में नहीं। उपन्यासों की संतुष्टि में "पेटिट बैकट्रैकिंग" हो सकती है, लेकिन बाइंडिंग को बरकरार रखने के दौरान समग्र लक्ष्य विफल नहीं होता है।

एक पतला, और शायद अनुपयोगी समाधान maplist/2 का उपयोग करना है।

?- length(L, 3), maplist(animal, L). 
L = [cat, cat, cat] ; 
L = [cat, cat, dog] ; 
L = [cat, cat, mouse] ; 
L = [cat, dog, cat] ; 
... 
L = [mouse, mouse, dog] ; 
L = [mouse, mouse, mouse]. 

आप सिर्फ एक विधेय को जोड़कर एक materialized डेटाबेस का उपयोग करने पर जा सकते हैं:

% just flips the arguments of member/2 
memberof(L, A) :- member(A, L). 

फिर हम findall/3 उपयोग कर सकते हैं काम करने के लिए उदाहरण के लिए, अपने उदाहरण इस तरह से प्राप्त करने के लिए आसान है :

?- findall(A, animal(A), Animals), 
    length(L, 3), 
    maplist(memberof(Animals), L). 

Animals = [cat, dog, mouse], 
L = [cat, cat, cat] ; 
Animals = [cat, dog, mouse], 
L = [cat, cat, dog] ; 
Animals = [cat, dog, mouse], 
L = [cat, cat, mouse] ; 
... 
Animals = [cat, dog, mouse], 
L = [mouse, mouse, dog] ; 
Animals = [cat, dog, mouse], 
L = [mouse, mouse, mouse]. 

यह स्पष्ट करना चाहिए कि lambda.pl मदद क्यों करेगा। आप सहायक विधेय की जरूरत नहीं होगी, तो आप बस लिख सकते हैं:

?- findall(A, animal(A), Animals), 
    length(L, 3), 
    maplist(\Animal^member(Animal, Animals), L). 

(untested)

तुम सच में बंधन और unbinding चर को धोखा देने पर आमादा हैं, तो मुझे लगता है कि आप एक बनाने के लिए जा रहे हैं अपने लिए दुःस्वप्न दुःस्वप्न, लेकिन एसडब्ल्यूआई-प्रोलॉग में global variable facility है जिसका आप उपयोग कर सकते हैं। मैं अस्पष्ट रूप से कहीं पढ़ना याद करता हूं कि asserta/retract इस कार्य के लिए अपर्याप्त हैं।

जितना अधिक मैं इसके बारे में सोचता हूं, उतना ही मुझे लगता है कि satisfyall/1 का सार्थक कार्यान्वयन नहीं होने वाला है जो maplist/2 से काफी अलग है, लेकिन मैं यह जानने के लिए उत्सुक हूं कि मैं गलत हूं।

+0

मैं lambda.pl से परिचित नहीं हूं, और अब तक मुझे मैपलिस्ट के बारे में पता नहीं था, लेकिन मैपलिस्ट मुझे 80% तरीके से प्रतीत होता है। मैं इसे बाद में आजमाउंगा और अपना प्रश्न अपडेट करूँगा! – Edmund

+0

मुझे उम्मीद है कि @ हार्डमाथ या कोई और 'संतुष्टि/1' के साथ आने का एक तरीका देखता है जो आपको वहां से बाकी तरीके से ले जाता है। मुझे सामान्य एकीकरण प्रक्रिया पर भरोसा करने के अलावा टेम्पलेट संरचना का उपयोग करने का सीधा तरीका नहीं दिखता है। उम्मीद है कि दूसरों के पास बेहतर कल्पनाएं होंगी और आगे बढ़ सकती हैं। :) –

+0

'जानवरों' को विश्व स्तर पर घोषित किया जाना चाहिए: 'मानचित्रसूची (पशु + \ पशु^सदस्य (पशु, पशु), एल) ' – false