2012-07-06 14 views
12

Ich habe eine Klausel wie folgt vor:zählen die Anzahl der Anrufe einer Klausel

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

diese Klausel folgen. Aber ich möchte wissen, wie oft conditional_combination() aufgerufen wird, bevor equal(X,[8,6,5,3,6,9]) wahr wird. Das Programm erzeugt eine Permutation, indem es einige Regeln befolgt. Und ich brauche, wie viele Permutation erzeugen müssen, um einen bestimmten Wert zu erhalten wie 865369.

Antwort

12

Was Sie eigentlich wollen, ist etwas anderes: Sie wollen die Anzahl der Antworten (bisher) eines Ziels zählen.

Das folgende Prädikat call_nth(Goal_0, Nth) folgt wie call(Goal_0), hat aber ein zusätzliches Argument, das angibt, dass die gefundene Antwort die n-te Antwort ist. Diese Definition ist sehr spezifisch für SWI oder YAP. Do nicht Verwenden Sie Dinge wie nb_setarg/3 in Ihren allgemeinen Programmen, aber verwenden Sie sie für gut gekapselte Fälle als diese. Selbst innerhalb dieser beiden Systeme ist die genaue Bedeutung dieser Konstrukte für den allgemeinen Fall nicht gut definiert. 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. 

Eine robustere Abstraktion Eclipse zur Verfügung gestellt:

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. 

So einfach umschlingen:

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

Ich sehe einen Weg, um einen ** Aggregator ** O (N) in Zeit ** und ** Raum mit solchen primitiven zu tun. Vielen Dank! – CapelliC

+0

Die Implementierung limit/2 und offset/2 müssen überdenken, vielleicht wäre das primitivere und universellere Prädikat call_nth/2. –

+0

Ich habe nicht erkannt, dass ein Ziel so genannt werden kann (die dritte Zeile der 'call_nth/2'-Auflistung). Ich dachte, man braucht immer 'call (Goal)', aber offensichtlich reicht 'Goal'! –

4

Wenn Sie SWI Prolog verwenden Sie nb_getval/2 und nb_setval/2 verwenden können, um zu erreichen, was Sie wollen:

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

Andere Prologe Haben Sie andere Möglichkeiten, um das gleiche zu tun, suchen Sie in Ihrer Prolog-Implementierung nach globalen Variablen. In diesem Snippet habe ich den Begriff ctr verwendet, um den aktuellen Zielzähler zu halten. Sie können dort einen beliebigen Begriff verwenden, der in Ihrem Programm nicht verwendet wird.

+1

Ein Aufruf von 'nb_setval/2' innerhalb' conditional_combination/1 'würde das Ergebnis beeinflussen. Ein Name wie 'ctr' könnte für eine andere Zählung verwendet werden ... – false

+0

@false: true, OP sollte einen beliebigen Ausdruck verwenden, der in seinem Programm nicht verwendet wird. – gusbro

+3

Der Punkt war, dass Sie das nicht garantieren können, ohne Ihr gesamtes Programm zu überprüfen. – false