2016-03-26 9 views
5

यह शायद एक समारोह की सबसे छोटी कार्यान्वयन कि PrologProlog और उलटे पांव लौटने

में Prolog के बारे में
count([], 0). 
count([_|B], T) :- count(B, U), T is U + 1. 

एक बात यह है कि मैं अभी भी चारों ओर मेरे सिर लपेटो नहीं कर सकते हैं एक सूची की लंबाई देता है की सीमाओं का लचीलापन है पैरामीटर के रूप में चर का उपयोग कर।

तो उदाहरण के लिए मैं count([a, b, c], 3). चला सकता हूं और true प्राप्त कर सकता हूं। मैं count([a, b], X). भी चला सकता हूं और X = 2. का उत्तर प्राप्त कर सकता हूं। विचित्र रूप से (कम से कम मेरे लिए) यह है कि मैं count(X, 3). भी चला सकता हूं और कम से कम एक परिणाम प्राप्त कर सकता हूं, जो कि X = [_G4337877, _G4337880, _G4337883] ; जैसा कुछ दिखता है, इससे पहले कि दुभाषिया एक अनंत लूप में गायब हो जाए। मैं count(X, A). जैसे कुछ "लचीला" भी चला सकता हूं और X = [], A = 0 ; X = [_G4369400], A = 1. प्राप्त कर सकता हूं, जो स्पष्ट रूप से अपूर्ण है लेकिन किसी भी तरह वास्तव में अच्छा है।

इसलिए मेरा बहुआयामी प्रश्न। क्या मैं किसी भी तरह प्रोलॉग को समझा सकता हूं कि count(X, 3). निष्पादित करते समय पहले परिणाम से परे न दिखें? क्या मैं किसी भी तरह Prolog को count(X, A). के लिए किसी भी समाधान का समाधान कर सकता हूं? क्या कोई सीमा है कि मैं किस प्रकार के समाधान उत्पन्न कर सकता हूं? इस विशिष्ट भविष्यवाणी के बारे में क्या है, जो मुझे सभी संभावित प्रकार के प्रश्नों के लिए सभी समाधान उत्पन्न करने से रोकता है?

उत्तर

3

यह शायद सबसे तुच्छ कार्यान्वयन

दृष्टिकोण से निर्भर करता है है: विचार करना

count(L,C) :- length(L,C). 

छोटे और कार्यात्मक। और यह आपके उपयोग के मामले के लिए भी काम करता है।

संपादित

पुस्तकालय CLP(FD) के लिए

:- use_module(library(clpfd)). 

count([], 0). 
count([_|B], T) :- U #>= 0, T #= U + 1, count(B, U). 

?- count(X,3). 
X = [_G2327, _G2498, _G2669] ; 
false. 

(आगे) की अनुमति देता है टिप्पणियों

को जवाब दे यह स्पष्ट रूप से किया गया व्यंग्य

नहीं, इस छाप देने के लिए खेद है। यह आपको अपने प्रश्न के उत्तर सिंथेटिक देने का प्रयास था। लंबाई/2 के कार्यान्वयन के हर विवरण - वास्तव में आपके कोड से काफी लंबा - हमें एक सामान्य और कुशल बिल्डिंग ब्लॉक देने के लिए ध्यान से भारित किया गया है।

कुछ सामान्य अवधारणा

मैं कहेंगे (पूर्ण) Prolog इस तरह के सामान्य अवधारणा होनी चाहिए। बहुत शुरुआत से, प्रोलॉग को हमें गणनात्मक तर्कों के बीच संबंधों का वर्णन करने वाले कम्प्यूटेशनल कार्यों को हल करने की आवश्यकता है। एक बार हमारे पास वर्णित हमारे संबंधों का वर्णन करते हैं, हम अपने 'ज्ञान डेटाबेस' से पूछ सकते हैं, और प्रोल सभी उत्तरों को विशिष्ट क्रम में गणना करने का प्रयास करता है।

unification और depth first search (बैकट्रैकिंग) जैसे उच्च स्तरीय अवधारणाएं इस मॉडल में कुंजी हैं।

अब, मैं आप दूसरा आदेश तरह var/1 निर्माणों, कि हम में के बारे में हमारी विधेय तर्क करने की अनुमति देने के लिए देख रहे हैं लगता है। इस तरह की संरचनाओं को (शुद्ध) प्रोलॉग में लिखा नहीं जा सकता है, और बढ़ते school of thinking को उनसे बचने की आवश्यकता है, क्योंकि इसका उपयोग करना मुश्किल है। इसलिए मैंने सीएलपी (एफडी) का उपयोग करके एक विकल्प पोस्ट किया, जो प्रभावी रूप से हमें में स्थिति में प्रभावी रूप से ढालता है। इस सवाल में विशिष्ट संदर्भ, यह वास्तव में हमें एक सरल और सुरुचिपूर्ण समाधान देता है।

मैं फिर से लागू करने की लंबाई

खैर, मैं इस के बारे में पता है, लेकिन कोशिश नहीं कर रहा हूँ के बाद से गिनती/2 उपनाम लंबाई/2, क्यों संदर्भ मॉडल का अध्ययन नहीं? (एसडब्ल्यूआई-प्रोलॉग साइट browsable source थी, लेकिन ऐसा लगता है कि यह अभी टूटा हुआ है)

+0

ओह हाँ, मुझे मूर्खतापूर्ण। – vasily

+0

@ vasily: क्या यह वास्तव में वह जवाब है जिसे आप चाहते थे? – false

+0

@false बिल्कुल नहीं। यह स्पष्ट रूप से कटाक्ष था, क्योंकि लंबाई की लाइब्रेरी कार्यान्वयन कोड की केवल 2 पंक्तियों की तुलना में अधिक लंबा है। – vasily

3

उत्तर count(X,3) क्वेरी के लिए आपको जो जवाब मिलता है वह वास्तव में बिल्कुल अजीब नहीं है। आप पूछ रहे हैं कि कौन सी सूचियों की लंबाई 3 है। और आपको 3 तत्वों के साथ एक सूची मिलती है। अनंत लूप प्रकट होता है क्योंकि आपके रिकर्सिव नियम के पहले लक्ष्य में चर बी और यू चरम हैं। आपके पास उस लक्ष्य से पहले कुछ भी नहीं है जो असफल हो सकता है। तो रिकर्सन का पालन करना हमेशा संभव है। CapelliC के संस्करण में आप प्रत्यावर्तन से पहले दूसरे नियम में 2 गोल है कि असफल हो, तो दूसरा तर्क हो सकता है कि 1. छोटे से यह स्पष्ट हो जाता है कि यदि आप इस थोड़ा बदल संस्करण पर विचार करें:

:- use_module(library(clpfd)). 

count([], 0). 
count([_|B], T) :- 
    T #> 0, 
    U #= T - 1, 
    count(B, U). 

आपकी क्वेरी

?- count(X,3). 

पहला नियम है, लेकिन एक दूसरे से मेल नहीं खाएगी और जब तक दूसरा तर्क 0. उस समय पहला नियम से मेल खाते हैं और परिणाम निकलेगा है रिकर्सिवली जारी रखने के लिए:

X = [_A,_B,_C] ? 

दूसरा नियम के सिर भी मिलान कर देंगे लेकिन इसके पहला गोल असफल क्योंकि T=0 देगा:

X = [_A,_B,_C] ? ; 
no 

अपने ऊपर संस्करण में हालांकि Prolog क्योंकि अनबाउंड चर बी और यू के दूसरे नियम की पुनरावर्ती लक्ष्य की कोशिश करेंगे और इसलिए असीम पाश।