2012-07-06 15 views
12

Mam klauzulę jak następuje:policzyć liczbę połączeń klauzuli

lock_open:- 
     conditional_combination(X), 
     equal(X,[8,6,5,3,6,9]),!, 
     print(X). 

klauzula ta sukces. Ale chcę wiedzieć, ile razy funkcja warunkowego_połączenia() jest wywoływana, zanim stanie się prawidłowa equal(X,[8,6,5,3,6,9]). program ma generować permutację poprzez przestrzeganie pewnych zasad. I muszę ile permutacji jest potrzebne do wygenerowania aby uzyskać określoną wartość podobnego 865369.

Odpowiedz

12

To, czego naprawdę chcesz, to coś innego: chcesz policzyć liczbę odpowiedzi (jak dotąd) na cel.

Następujący predykat call_nth(Goal_0, Nth) zastępuje, tak jak call(Goal_0), ale ma dodatkowy argument, który wskazuje, że znaleziona odpowiedź jest n-tą odpowiedzią. Ta definicja jest bardzo specyficzna dla SWI lub YAP. Czy nie używać rzeczy takich jak nb_setarg/3 w swoich ogólnych programach, ale używaj ich do dobrze zakapsułowanych przypadków jak ten. Nawet w tych dwóch systemach dokładne znaczenie tych konstrukcji nie jest dobrze zdefiniowane w ogólnym przypadku. Here is a definition for SICStus.

 
call_nth(Goal_0, C) :- 
    State = count(0,_), % note the extra argument which remains a variable 
    Goal_0, 
    arg(1, State, C1), 
    C2 is C1+1, 
    nb_setarg(1, State, C2), 
    C = C2. 

Bardziej wytrzymałe abstrakcji jest przez Eclipse:

call_nth(Goal_0, Nth) :- 
    shelf_create(counter(0), CounterRef), 
    call(Goal_0), 
    shelf_inc(CounterRef, 1), 
    shelf_get(CounterRef, 1, Nth). 
 
?- call_nth(between(1,5,I),Nth). 
I = Nth, Nth = 1 ; 
I = Nth, Nth = 2 ; 
I = Nth, Nth = 3 ; 
I = Nth, Nth = 4 ; 
I = Nth, Nth = 5. 

Więc po prostu owinąć go wokół:

 
lock_open :- 
    call_nth(conditional_combination(X), Nth), 
    X = [8,6,5,3,6,9], 
    !, 
    .... 
+1

Widzę sposób na ** agregator ** O (N) w czasie ** i ** za pomocą takich prymitywów. Dzięki! – CapelliC

+0

Musimy ponownie przemyśleć implementację limitu/2 i przesunięcia/2, może bardziej prymitywnym i uniwersalnym predykatem będzie call_nth/2. –

+0

Nie zdawałem sobie sprawy, że cel można nazwać w ten sposób (trzecia linia listy 'call_nth/2'). Myślałem, że zawsze potrzebuję 'call (Goal)', ale oczywiście wystarczy 'Goal'! –

4

Jeśli używasz SWI Prolog można użyć nb_getval/2 i nb_setval/2, aby osiągnąć to, co chcesz:

lock_open:- 
    nb_setval(ctr, 0), % Initialize counter 
    conditional_combination(X), 
    nb_inc(ctr), % Increment Counter 
    equal(X,[8,6,5,3,6,9]), 
    % Here you can access counter value with nb_getval(ctr, Value) 
    !, 
    print(X). 

nb_inc(Key):- 
    nb_getval(Key, Old), 
    succ(Old, New), 
    nb_setval(Key, New). 

Inne prologs miej inne sposoby, aby zrobić to samo, poszukaj zmiennych globalnych w swojej implementacji prologu. W tym fragmencie użyłem terminu ctr do przechowywania aktualnego licznika bramek. Możesz użyć dowolnego terminu, który nie jest używany w twoim programie.

+1

wezwanie do 'nb_setval/2' ciągu' conditional_combination/1' wpłynęłoby na wynik. Nazwa taka jak 'ctr' może być użyta do innych obliczeń ... – false

+0

@false: true, OP powinien używać dowolnego terminu nieużywanego w jego programie. – gusbro

+3

Chodziło o to, że nie możesz tego zagwarantować bez inspekcji całego programu. – false

Powiązane problemy