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?
3 answers
En SWI-Prolog:
aggregate_all(count, is_man(X), Count).
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)).
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).
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