2011-05-08 14 views
8

मुझे सभी X, some_predicate(X) और वास्तव में X पर गिनने की आवश्यकता है। ऐसा करने का सबसे अच्छा तरीका क्या है?swi-prolog में कुल/3

पहला सुराग इसे सभी को ढूंढना है, एक सूची में जमा होना और इसकी लंबाई वापस करना है।

countAllStuff(X) :- 
    findall(Y 
      , permutation([1,2,3,4,5,6,7,8,9,10], Y) 
      , List 
      ), 
    length(List, X). 

(permutation/2 केवल दिखा कई भिन्न रूप देखते हैं कि उदाहरण है और यह बुरा जिस तरह से यह सब इकट्ठा करने के लिए है)

जाहिर है, मैं है स्टैक-अतिप्रवाह।

?- countAllStuff(X). 
ERROR: Out of global stack 

से, मैं findallsetof और कुछ भी नहीं परिवर्तन करने के लिए बदलने के लिए कोशिश कर रहा हूँ।

आखिरकार, मैंने aggregate (क्लिक करने योग्य) की भविष्यवाणी की है और इसका उपयोग करने की कोशिश की है।

?- aggregate(count, permutation([1,2,3,4], X), Y). 
X = [1, 2, 3, 4], 
Y = 1 . 

?- aggregate(count, [1,2,3,4], permutation([1,2,3,4], X), Y). 
X = [1, 2, 3, 4], 
Y = 1 ; 
X = [1, 2, 4, 3], 
Y = 1 ; 

यह सब गलत है, मुझे लगता है। मुझे कुछ

?- aggregate(count, permutation([1,2,3,4], X), Y). 
Y = 24 . 

1) मैं कुछ गलत क्या कर रहा हूं?

2) मैं सही उत्तर पाने के लिए भविष्यवाणी कैसे कर सकता हूं?

उत्तर

8

, एक existentially मात्रा निर्धारित चर का प्रयोग के रूप में आप setof के साथ होता है:

?- aggregate(count, X^permutation([1,2,3,4], X), N). 
N = 24. 
+0

मिल एक्स^उस मामले में क्रमचय क्या है? –

+5

@ garm0nboz1a: 'X ^' का अर्थ है "वहां मौजूद है 'एक्स," इसलिए संपूर्ण सूत्र का अर्थ है "क्रमपरिवर्तन ([1,2,3,4], एक्स) के तरीकों की संख्या गिनती है *' सफल कुछ * 'एक्स' और उस नंबर को कॉल करें 'एन'।" –

2

वहाँ भी aggregate_all/3 है:

?- aggregate_all(count, permutation([1, 2, 3, 4], _), Total). 
Total = 24. 

हालांकि, जहां तक ​​क्रम और ढेर अतिप्रवाह चिंतित हैं यह प्रदर्शन करने के लिए लगता है आपके findall + length समाधान के लिए समान रूप से अच्छी तरह से:

?- N is 10^7, time(aggregate_all(count, between(1, N, _), Total)). 
% 10,000,022 inferences, 5.075 CPU in 5.089 seconds (100% CPU, 1970306 Lips) 
N = Total, Total = 10000000. 

?- N is 10^7, time((findall(X, between(1, N, _), L), length(L, Total))). 
% 10,000,013 inferences, 4.489 CPU in 4.501 seconds (100% CPU, 2227879 Lips) 
N = 10000000, 
L = [_G30000569, _G30000566, _G30000545|...], 
Total = 10000000. 

?- N is 10^8, aggregate_all(count, between(1, N, _), Total). 
ERROR: Out of global stack 

?- N is 10^8, findall(X, between(1, N, _), L), length(L, Total). 
ERROR: Out of global stack 

आप assert/retract का उपयोग कर समाधान भरोसा कर सकते हैं, यह काफी धीमी है लेकिन "ढेर से बाहर" समस्या से बचने करता है:,

?- assert(counter(0)), N is 10^8, between(1, N, _), 
    retract(counter(C)), C1 is C + 1, assert(counter(C1)), fail 
    ; retract(counter(C)). 
C = 100000000. 
3

SWI-Prolog में एक बहुत अधिक कुशल संस्करण है भी करने से बच सकें वैश्विक स्टोर लॉकिंग। तो बस nb_setval और nb_getval का उपयोग करके आप कम से कम 3 बार प्रदर्शन (मल्टीथ्रेडिंग पर अधिक) प्राप्त करते हैं। बस थोड़ी देर पहले समाधान की गिनती पर एक और सवाल था। प्रोलॉग सीखते समय एकत्रीकरण का आधार होने के नाते यह एक स्पष्ट रोक बिंदु है। दक्षता लाभ हम इन शब्दार्थ बराबर कॉल monothread का उपयोग कर पाने का मूल्यांकन करने के लिए:

count_solutions(Goal, N) :- 
assert(count_solutions_store(0)), 
repeat, 
( call(Goal), 
    retract(count_solutions_store(SoFar)), 
    Updated is SoFar + 1, 
    assert(count_solutions_store(Updated)), 
    fail 
; retract(count_solutions_store(N)) 
), !. 
:- dynamic count_solutions_store/1. 

% no declaration required here 
count_solutions_nb(Goal, N) :- 
    nb_setval(count_solutions_store, 0), 
    repeat, 
    ( call(Goal), 
     nb_getval(count_solutions_store, SoFar), 
     Updated is SoFar + 1, 
     nb_setval(count_solutions_store, Updated), 
     fail 
    ; nb_getval(count_solutions_store, N) 
    ), !. 

parent(jane,dick). 
parent(michael,dick). 
parent(michael,asd). 

numberofchildren(Parent, N) :- 
    count_solutions_nb(parent(Parent, _), N). 

many_solutions :- 
    between(1, 500000, _). 

time_iso :- 
    time(count_solutions(many_solutions, N)), 
    write(N), nl. 

time_swi :- 
    time(count_solutions_nb(many_solutions, N)), 
    writeln(N). 

अपने सिस्टम पर, मैं

?- [count_sol]. 
% count_sol compiled 0,00 sec, 244 bytes 
true. 

?- time_iso. 
tim% 1,000,006 inferences, 2,805 CPU in 2,805 seconds (100% CPU, 356510 Lips) 
500000 
true. 

?- time_swi. 
% 2,000,010 inferences, 0,768 CPU in 0,768 seconds (100% CPU, 2603693 Lips) 
500000 
true. 
+0

क्या नवीनतम एसडब्ल्यूआई-प्रोलॉग लागू नहीं होता है? –

+1

@ j4nbur53: हाँ, * aggregate_all * गिनती, योग, न्यूनतम, अधिकतम उपयोग nb_setval – CapelliC