Existe-t-il un programme capable de dessiner un arbre de recherche de requêtes Prolog ?
-
12-11-2019 - |
Question
Je me demandais s'il existe un outil capable de dessiner un arbre de recherche étape par étape d'un programme Prolog ?Merci.
La solution
Si votre système Prolog a un débogueur personnalisable, vous pouvez facilement Écrivez votre propre code de collecte de graphes d'exécution. Assumer votre PROG System a un appel de raccordement de rappel de Hook_Tracing / 2 comme dans Jekejeke Prolog . Ensuite, nous pouvons continuer et inspecter le cadre actuel et le Cadre parent pour créer un lien dans le graphique. Voici le code:
goal_tracing(call, F) :-
frame_property(F, sys_call_indicator(N, A)),
frame_property(F, sys_parent_frame(G)),
frame_property(G, sys_call_indicator(M, B)),
!,
update_link(N / A, M / B).
goal_tracing(_, _).
:- dynamic link/2.
update_link(A, B) :-
link(A, B),
!.
update_link(A, B) :-
assertz(link(A, B)).
Comme on peut le voir, nous examinons uniquement le port d'appel et nous examinons seulement la indicateur de prédicat. Mais d'autres approches sont également possibles qui collectent plus de données. Maintenant, nous avons besoin d'une utilité pour afficher le résultat. Il n'y a que une réinitialisation à appeler avant la collection et un spectacle à appeler après la collection:
reset :-
retract(link(_, _)), fail.
reset.
show :-
write('http://yuml.me/diagram/scruffy/class/'),
link(A, B),
write(([B] -> [A])),
write(', '),
fail.
show.
Nous produisons un lien qui est compris par Yuml.Me . Permet de le faire essayer avec le programme factorial PEERO. Le code de programme semble comme suit:
add(n, X, X).
add(s(X), Y, Z) :-
add(X, s(Y), Z).
mul(n, _, n).
mul(s(X), Y, Z) :-
mul(X, Y, H),
add(Y, H, Z).
fac(n, s(n)).
fac(s(X), Y) :-
fac(X, H),
mul(s(X), H, Y).
Nous pouvons exécuter le collecteur comme suit:
?- reset.
?- trace.
?- fac(s(s(n)),X).
X = s(s(n))
?- nodebug.
?- show.
http://yuml.me/diagram/scruffy/class/[fac / 2] -> [fac / 2], [fac / 2] -> [mul / 3], [mul / 3] -> [mul / 3], [mul / 3] -> [add / 3], [add / 3] -> [add / 3], Yes
On peut ensuite coller l'URL dans un navigateur et verra le diagramme. Supprimer le ", oui" à la fin de l'URL. Voici le résultat:
meilleures salutations
Autres conseils
Les arbres de recherche Prolog sont souvent trop gros pour être examinés étape par étape, mais le dessin pourrait être plutôt simple et intéressant aussi. Peut-être que je vais essayer d'écrire un à l'aide de la bibliothèque HTML_WRITE. Dans ce cas, je signalerai le résultat.
Entre-temps Swi-Prolog a une représentation plutôt particulière dans son débogueur . Il existe des détails intéressants sur l'arbre du programme Prolog. Ce n'est pas si facile à utiliser et je dois avouer que je n'ai toujours pas lu les documents. Cependant, j'ai utilisé fréquemment le débogueur. Vous pouvez naviguer dans l'arborescence et les variables instanciées sur les différents nœuds. C'est
visualisation de l'espace de recherche Prolog est une tâche intéressante qui n'est pas simple!
edit J'ai oublié de mentionner que XPCE a la capacité d'afficher de grands arbres. Si vous avez déjà
Jeter un coup d'œil à sldnfdraw pour swi-prolog, cela fonctionne à merveille, le seul problème que j'ai trouvé est que les termes ne peuvent pas contenir de traits de soulignement, mais j'ai déjà envoyé un e-mail à son auteur pour le signaler.
Il crée un fichier tex avec une représentation arborescente, puis, avec quelques commandes bash, le transforme en png pour la visualisation.
latex file.tex
dvipdf file.dvi
pdfcrop file.pdf
pdftoppm file-crop.pdf|pnmtopng > file.png
Je recommande également d'ajouter \usepackage[landscape]{geometry}
donnez un espace supplémentaire à l'arbre.
Je résolvai-je d'une manière différente ... jeter un coup d'œil à: https://github.com/reahaas/prolog-trace-a-tree
i Exécution du programme de Prolog avec Trace, qui me donnez une sortie de la trace comme texte.Chaque étape d'une ligne différente. Enregistrez cette sortie de trace dans un fichier.Cela devrait ressembler à ceci:
?- trace,there_is_way(telaviv,heifa).
Call: (9) there_is_way(telaviv, heifa) ? creep
Call: (10) there_is_way(telaviv, heifa, nil) ? creep
Call: (11) road_from(telaviv, heifa) ? creep
Call: (12) road(telaviv, heifa) ? creep
Fail: (12) road(telaviv, heifa) ? creep
Fail: (11) road_from(telaviv, heifa) ? creep
Redo: (10) there_is_way(telaviv, heifa, nil) ? creep
Call: (11) road_from(telaviv, _4236) ? creep
Call: (12) road(telaviv, _4236) ? creep
Utilisez ensuite ce code Python pour imprimer l'arborescence des appels: Sa construction de l'arbre s'appuyant sur le premier mot de la trace: {appel, échec, sortie, redo}.
AVIS: Changez le chemin de fichier / nom dans le code (avec Ouvrir (...)).
from pptree import *
import os
def get_first_word(line):
if line is "":
return
words = line.split()
if len(words) > 0:
first_word = words[0]
return first_word
def add_node(current, line):
if current is None:
return Node("head" + line, None)
else:
return Node(line, current)
with open("/home/vagrant/openu/prolog/trace_monkey.txt", 'r') as trace_file:
current = None
while True:
line = trace_file.readline()
if line.strip() == "": # run till it face an empty string.
break
first_word = get_first_word(line)
if current is None:
call_tree = add_node(current, line)
current = call_tree
elif first_word == "Call:":
current = add_node(current, line)
elif first_word == "Exit:":
add_node(current, line) # get_assignment(line))
current = current.parent
elif first_word == "Fail:":
add_node(current, line)
current = current.parent
elif first_word == "Redo:":
current = add_node(current, line)
print_tree(call_tree)
Ceci est les résultats:
Pour voir les résultats, coller l'arborescence de texte au bloc-notes ++ et zoom arrière :)