This example makes use of the persistence file created in this post and converts the facts into a GraphViz dot file. Using GraphViz the dot file can be converted to a PDF, SVG, etc.
Typically DCGs are demonstrated by parsing text into a structure, this does the opposite and converts structures into text.
:- module(module_graph,[
write_graph/1
]).
:- use_module(library(persistency)).
:- use_module(library(fileutils)).
:- set_prolog_flag(double_quotes, codes).
:- persistent
uses(super:atom,module:atom),
imports(module:atom,import:atom).
:- initialization(db_attach('module.journal', [])).
write_graph(Filepath) :-
graph(Graph),
with_output_to_file(Filepath,write(Graph)).
nodes(Nodes) :-
setof(Super,uses(Super,_),A),
setof(Module,uses(_,Module),B),
merge(A,B,Nodes), !.
edges(Edges) :-
setof(uses(Super,Module),uses(Super,Module),Edges).
graph(Graph) :-
phrase(graph,Codes,[]),
string_codes(Graph,Codes).
graph -->
{
nodes(Nodes),
edges(Edges)
},
header,
nodes(Nodes),
edges(Edges),
footer.
header -->
"digraph module_graph\n\c
{\n\c
overlap=false;\n\c
spline=true;\n\c
contentrate=true;\n\c
node [shape=box,fontname=\"Times\"];\n\c
edge [arrowhead=vee];\n\c
\n\c
labeljust=\"l\";\n\c
fontname=\"Times Bold\";".
footer -->
"\n}".
nodes([H|T]) -->
node(H),
"\n",
nodes(T).
nodes([]) --> [].
node(Name) -->
{ string_codes(Name,Codes) },
"\"",
Codes,
"\" [fontname=\"Times Bold\",style=\"bold\"];".
edges([uses(A,B)|T]) -->
edge(A,B),
"\n",
edges(T).
edges([]) --> [].
edge(A,B) -->
{
string_codes(A,A_codes),
string_codes(B,B_codes)
},
"\"",
A_codes,
"\" -> \"",
B_codes,
"\"",
";".
Example usage:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.5-8-ge14460a94)
?- working_directory(_,'C:/Users/Groot/Documents').
true.
% If you created the persistent file from the other post you can skip this step.
?- ['module tools'].
true.
% If you created the persistent file from the other post you can skip this step.
?- init.
true.
?- ['module graph'].
true.
?- write_graph('module_graph.dot').
true.
To convert the dot file to an SVG. (Example is in a Windows batch file.)
SET PATH="C:\Program Files (x86)\Graphviz2.38\bin"
dot -Tsvg module_graph.dot -o module_graph.svg
Double clicking on an SVG file in Windows File Explorer should load the file into you preferred Internet browser for viewing.
The spacing of the text in the dot file could be better, but once you start using this how often will you really care about the formatting of the text in the dot file?
Also see:
https://js.cytoscape.org/
dot-app - Import/export of Graphviz files in Cytoscape
https://protege.stanford.edu/products.php - Protégé is a free, open-source platform that provides a growing user community with a suite of tools to construct domain models and knowledge-based applications with ontologies.
EDIT
If you want to be able to draw the graphs in an Internet browser and then drag the nodes around with a mouse try this tutorial: Getting started with Cytoscape.js
The tutorial is a bit dated.
The JavaScript can be downloaded from GitHub: https://github.com/cytoscape/cytoscape.js
Copy cytoscape.min.js
from directory cytoscape.js-unstable\dist
to directory getting-started
In the instructions where it notes to use
<script src='cytoscape.js'></script>
instead use
<script src='cytoscape.min.js'></script>
Have not finished the demo but since Cytoscape.js accesses the nodes and edges as
elements: [
// nodes
{ data: { id: 'a', name: 'A' } },
{ data: { id: 'b', name: 'B' } },
{ data: { id: 'c', name: 'C' } },
{ data: { id: 'd', name: 'D' } },
{ data: { id: 'e', name: 'E' } },
{ data: { id: 'f', name: 'F' } },
// edges
{ data: { id: 'ab', source: 'a', target: 'b'} },
{ data: { id: 'cd', source: 'c', target: 'd'} },
{ data: { id: 'ef', source: 'e', target: 'f'} },
{ data: { id: 'ac', source: 'a', target: 'c'} },
{ data: { id: 'be', source: 'b', target: 'e'} }
]
modifying the code used for GraphViz to work with Cytoscape should be easy. I plan to document this in detail and post it.