Prolog count el número de veces que un predicado es verdadero


Quiero contar el número de veces que un predicado personalizado es verdadero. Por ejemplo, tengo el siguiente código:

is_man(john).
is_man(alex).
?:-is_man(X).

X devolverá john, entonces si presiono punto y coma también devolverá alex, entonces false.

Quiero construir algo como:

count(is_man(X), Count).

Y esto para volver

Count = 2

¿Cómo puedo hacer eso?

 23
Author: Victor Blaga, 2011-05-19

3 answers

En SWI-Prolog:

aggregate_all(count, is_man(X), Count).
 27
Author: Kaarel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-19 14:37:30

Para una solución Prolog estándar ISO, puede usar findall/3 para producir una lista de todas las soluciones, luego establecer Count a la longitud de la lista resultante. Podría ser un poco complicado envolver esto en un predicado definido por el usuario count/2 como usted propone, porque necesitamos formar el primer argumento de findall/3 de una manera que tenga en cuenta cualquier variable libre (no ligada) en el objetivo que desea pasar como el primer argumento de count/2.

Muchos prólogos proporcionan para " contadores "u otras formas de valores globales mutables, una extensión no estándar, que podría usarse en conexión con un" bucle " impulsado por falla para hacer el mismo recuento. Un poco más engorroso pero ateniéndose a la letra del estándar Prolog sería usar assert y retract para crear su propio "contador" ajustando un hecho dinámico.

A continuación se ilustra este último enfoque. Hacerlo "multithread seguro" requeriría lógica adicional.

count(Goal,_) :-
    setGoalCount(0),
    call(Goal),
    incGoalCount(1),
    fail.              /* or false in some Prologs */
count(_,Count) :-
    getGoalCount(Count).

setGoalCount(_) :-
    retract(getGoalCount(_)),
    fail.
setGoalCount(X) :-
    assert(getGoalCount(X)).

incGoalCount(Y) :-
    retract(getGoalCount(X)),
    !,
    Z is X + Y,
    assert(getGoalCount(Z)).
 11
Author: hardmath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-19 16:46:39

count(P,Count) :-
        findall(1,P,L),
        length(L,Count).
 5
Author: 尾崎隆大,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-19 22:24:42