Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a program that can draw a search tree of Prolog queries?

I was wondering if there exists a tool that can draw a step-by-step search tree of a Prolog program? Thanks.

like image 979
IDDQD Avatar asked Feb 25 '12 21:02

IDDQD


2 Answers

Take a look at sldnfdraw for swi-prolog it works like a charm, the only issue I found with it is that the terms cannot contain underscores, but I've already sent an email to its author reporting it.

It creates a tex file with a tree representation, then with some bash commands transform it to png for visualization.

latex file.tex
dvipdf file.dvi
pdfcrop file.pdf
pdftoppm file-crop.pdf|pnmtopng > file.png

I also recommend adding \usepackage[landscape]{geometry} give extra space to the tree.

like image 154
nicoabie Avatar answered Nov 18 '22 00:11

nicoabie


I solved it in a different way... take a look at: https://github.com/reahaas/prolog-trace-to-tree

I run the program in prolog with trace, that give me an output of the trace as text. Each step in a different line. Save this trace output to a file. it should look like this:

?- 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

Then use this python code to print the calls trace tree: Its build the tree relying on the first word of the trace: {Call, Fail, Exit, Redo}.

notice: change the file path/name in the code (with open(...)).

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)

This is the results:

To see the results, paste the text tree to notepad++ and zoom out :) enter image description here

like image 37
Rea Haas Avatar answered Nov 18 '22 00:11

Rea Haas