Existe-t-il un programme capable de dessiner un arbre de recherche de requêtes Prolog ?

StackOverflow https://stackoverflow.com/questions/9448148

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

Était-ce utile?

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:

graphique d'appel

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

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à avoir l'arbre à la preuve, affichant qu'il devrait être très facile. Il suffit d'ouvrir le spectateur. Il devrait y avoir quelques exemples dans l'aide manuelle de XPCE. Vous pouvez baser l'affichage à ce sujet.

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 :) Entrez la description de l'image ici

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top