2012-07-06 13 views
12

tengo una cláusula como siguiente:contar el número de llamadas de una cláusula

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

esta cláusula tenga éxito. Pero quiero saber cuántas veces se llama a conditional_combination() antes de que equal(X,[8,6,5,3,6,9]) se haga verdadero. el programa es generar una permutación siguiendo algunas reglas. Y necesito el número de permutaciones se necesita generar para obtener un valor particular como 865369.

Respuesta

12

Lo que realmente quieres es algo diferente: quieres contar el número de respuestas (hasta ahora) de un objetivo.

El siguiente predicado call_nth(Goal_0, Nth) tiene éxito como call(Goal_0) pero tiene un argumento adicional que indica que la respuesta encontrada es la n-ésima respuesta. Esta definición es altamente específica para SWI o YAP. Haga no utilice cosas como nb_setarg/3 en sus programas generales, pero úselos para casos bien encapsulados como este. Incluso dentro de los esos dos sistemas, el significado preciso de estos constructos no está bien definido para el caso general. 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. 

Una abstracción más robusto es proporcionada por 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. 

Así que simplemente se envuelve alrededor:

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

Veo una forma de hacer ** un agregador ** O (N) en el tiempo ** y ** espacio usando dicha primitiva. ¡Gracias! – CapelliC

+0

Tiene que replantearse el límite/2 y la implementación offset/2, tal vez el predicado más primitivo y universal sería call_nth/2. –

+0

No me di cuenta de que un objetivo puede llamarse así (la tercera línea del listado 'call_nth/2'). Pensé que uno siempre necesita 'call (Goal)', pero obviamente, ¡solo 'Goal' es suficiente! –

4

Si está utilizando SWI-Prolog puede utilizar nb_getval/2nb_setval/2 y para lograr lo que quiere:

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

Otros prólogos tener otros medios para hacer lo mismo, buscar variables globales en la implementación de su prólogo. En este fragmento usé el término ctr para contener el contador de objetivos actual. Puede usar cualquier término que no se use en su programa.

+1

Una llamada a 'nb_setval/2' 'dentro conditional_combination/1' afectaría el resultado. Un nombre como 'ctr' podría usarse para otro conteo ... – false

+0

@false: verdadero, OP debería usar cualquier término no utilizado en su programa. – gusbro

+3

El punto es que no puede garantizar eso sin inspeccionar todo su programa. – false

Cuestiones relacionadas