# SWI Dependency Graph

**URL:** <https://swi-prolog.discourse.group/t/swi-dependency-graph/5978>\
**Category:** General\
**Created:** [November 28, 2022, 9:53pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978 "2022-11-28T21:53:25Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![edmcman](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/edmcman/32/1712_2.png) [@edmcman](https://swi-prolog.discourse.group/u/edmcman)\
**Post date:** [November 28, 2022, 9:53pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/1 "2022-11-28T21:53:25Z")

</div>

Are there any tools that can produce a dependency graph between predicates?

For example,

```prolog
foo :- bar.

```

would result in an edge from `foo` to `bar`. It doesn’t seem like it would be very difficult to create, which leads me to wonder if someone already has done it.

I know logtalk can do this via the diagrams tool, but my application lives in a bunch of different files, and that doesn’t seem like it would be easy to load in logtalk.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [November 28, 2022, 9:57pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/2 "2022-11-28T21:57:13Z")

</div>

SWI-Prolog XREF — [Cross-Referencing Tool](https://www.swi-prolog.org/gxref.html)

---

<div class="post-metadata">

**Author:** ![edmcman](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/edmcman/32/1712_2.png) [@edmcman](https://swi-prolog.discourse.group/u/edmcman)\
**Post date:** [November 28, 2022, 10:19pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/3 "2022-11-28T22:19:43Z")

</div>

Thanks @EricGT. The exact tool did not help, but it did lead me to find `library(prolog_xref)` and `library(prolog_codewalk)` which I think should do the trick.

[Using prolog\_walk\_code/1 to identify meta predicate calls?](https://swi-prolog.discourse.group/t/using-prolog-walk-code-1-to-identify-meta-predicate-calls/2977/1) also looks relevant.

---

<div class="post-metadata">

**Author:** ![edmcman](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/edmcman/32/1712_2.png) [@edmcman](https://swi-prolog.discourse.group/u/edmcman)\
**Post date:** [November 28, 2022, 10:22pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/4 "2022-11-28T22:22:57Z")

</div>

I was able to use call\_graph.pl in the other thread to accomplish what I wanted.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [November 29, 2022, 8:18am UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/5 "2022-11-29T08:18:37Z")

</div>

Yes, both `library(prolog_xref)` and `library(prolog_codewalk)` can create the data. Generate a `.dot` file and call graphviz and you are done. Knowing your program, I doubt it will be possible to make sense of the enormous graph. I recently wrote a similar thing for a moderate size s(CASP) program. That was barely manageable after tweaking the rules to omit a lot of stuff we considered irrelevant.

IMO a general call graph is not so useful. A dependency graph at the file/module level can work (gxref/0 can make that). Specific partial graphs may also be (the connections between a (small) set of predicates, mutual recursive loops, etc.).

**edit** , might be that the PDT plugin for the Eclipse IDE can do graphs?

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [November 29, 2022, 8:55am UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/6 "2022-11-29T08:55:47Z")

</div>

Of related interest:

[Generating Cytoscape.js graphs with SWI-Prolog](https://swi-prolog.discourse.group/t/generating-cytoscape-js-graphs-with-swi-prolog/2815)

The wiki and related info still need a lot of polishing so unless you have the time to work past the glossed over parts just keep it in mind for later. 🙂

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [November 29, 2022, 12:24pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/7 "2022-11-29T12:24:41Z")

</div>

> [@jan](#):
>
> Knowing your program, I doubt it will be possible to make sense of the enormous graph.

[Cytoscape](https://cytoscape.org/) that @EricGT mentioned might be another way to handle those enormous graphs. It outgrew its origins long ago and seems to be a really nifty tool.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [November 29, 2022, 12:58pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/8 "2022-11-29T12:58:35Z")

</div>

> [@Boris](#):
>
> [Cytoscape](https://cytoscape.org/) that @EricGT mentioned

Be warned that [Cytoscape](https://cytoscape.org/) is a different code base than [Cytoscape.js](https://js.cytoscape.org/). I have not used Cytoscape which uses Java. Cytoscape.js obviously uses JavaScript and needs a running server to present web pages.

The most complete example of using Cytoscape.js that I posted is found in this [reply](https://swi-prolog.discourse.group/t/wiki-discussion-generating-cytoscape-js-graphs-with-swi-prolog/2816/6), click `Details - Click triangle to expand.` to see the code. Note that that example uses a [Node.js](https://nodejs.org/en/) server but IIRC I was also able to swap that out for an [SWI-Prolog HTTP server](https://www.swi-prolog.org/pldoc/doc_for?object=section(%27packages/http.html%27)) thus obviating the need for node.js. The nice thing about that example is that it uses JSON data files which are easily created from [SWI-Prolog dictionaries](https://www.swi-prolog.org/pldoc/man?section=bidicts) using IIRC [json\_write\_dict/N](https://www.swi-prolog.org/pldoc/doc/_SWI_/library/http/json.pl). See  
[Json\_dict/2 - Helpful for learning how to use JSON with SWI-Prolog dict](https://swi-prolog.discourse.group/t/json-dict-2-helpful-for-learning-how-to-use-json-with-swi-prolog-dict/4450) for caveats. 🙂

---

<div class="post-metadata">

**Author:** ![edmcman](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/edmcman/32/1712_2.png) [@edmcman](https://swi-prolog.discourse.group/u/edmcman)\
**Post date:** [November 29, 2022, 1:25pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/9 "2022-11-29T13:25:49Z")

</div>

Thanks for all the advice.

Wow, the full Cytoscape example in Prolog is impressive 🙂 It makes me think perhaps I should try [https://adventofcode.com/](https://adventofcode.com/) in Prolog.

@jan I may be able to constrain the graph enough that GraphViz can handle it… we’ll see. This is actually related to better understanding rule ordering and negations.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [November 29, 2022, 1:48pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/10 "2022-11-29T13:48:03Z")

</div>

> [@Boris](#):
>
> It outgrew its origins long ago and seems to be a really nifty tool.

It is not so much the tool I’m worried about, but the human trying to read and understand such enormous graphs 🙂 Technically, both Graphviz and Cytoscape can probably render the graph. You need to zoom in very deep to get the labels readable though, loosing all overview. In the mentioned project we used Cytoscape.js. It is less good at compact placements of nodes with varying size labels and routing edges around nodes than Graphviz. It is a lot easier to add some interactivity to the graph. So, we added search to highlight and enlarge matching nodes and their (direct) dependencies and hovering the graph with similar effects. Hopefully that will at some point become available.

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [November 29, 2022, 2:21pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/11 "2022-11-29T14:21:42Z")

</div>

When I used it (but this was a more than 10 years ago) Cytoscape was able to show only parts of the network, among many other things. My memory is not what it used to be though, I might be wrong. The filtering was based on node/edge properties so this might not be immediately available with a call graph. Maybe best ignore me on the topic 🙂 I most definitely used Cytoscape for different kinds of networks.

---

<div class="post-metadata">

**Author:** ![edmcman](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/edmcman/32/1712_2.png) [@edmcman](https://swi-prolog.discourse.group/u/edmcman)\
**Post date:** [November 29, 2022, 6:40pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/12 "2022-11-29T18:40:50Z")

</div>

Is there a way to create IDs based on structural equivalence? I’m trying to put these terms as graph nodes, but they contain free variables.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [November 29, 2022, 7:00pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/13 "2022-11-29T19:00:04Z")

</div>

variant\_sha1/2 looks like a good candidate. Another way would be to use numbervars/4 with the option `singleton(true)` and write to an atom with the option `numbervars(true)`. That is more complex, but provides a readable identifier.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [November 29, 2022, 7:16pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/14 "2022-11-29T19:16:37Z")

</div>

> [@edmcman](#):
>
> Is there a way to create IDs based on structural equivalence?

You might find this of value:

[Structurally equivalent (=@=) and numbervars/1](https://swi-prolog.discourse.group/t/structurally-equivalent-and-numbervars-1/5244)

Also [Graph Theory FAQs: 03. Isomorphism Using Adjacency Matrix](https://www.youtube.com/watch?v=UCle3Smvh1s)

---

<div class="post-metadata">

**Author:** ![grossdan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/grossdan/32/23_2.png) [@grossdan](https://swi-prolog.discourse.group/u/grossdan)\
**Post date:** [November 30, 2022, 3:50pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/15 "2022-11-30T15:50:54Z")

</div>

Jan, I am curious …

When a graph / program gets so large that become hard to understand even with a dependency graph tool – does it mean that its architectural / modular design is rather at fault …

What would best practice be …

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [November 30, 2022, 5:19pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/16 "2022-11-30T17:19:21Z")

</div>

An program easily consists of thousands of predicates … A hundred labeled predicate nodes with edges between them is already getting hard to grasp.

> [@grossdan](#):
>
> What would best practice be …

I guess that depends on the size, structure and what you want to know about the program. Typically being able to navigate to callers and callees satisfies for me. Very infrequently I have harder questions where my solution was to write Prolog queries over the dependency graph.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [November 30, 2022, 5:51pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/17 "2022-11-30T17:51:33Z")

</div>

> [@jan](#):
>
> [A] program easily consists of thousands of predicates

Wouldn’t modules help in limiting the interconnections, allowing “zooming” in or out to get different levels of granularity? Also, one would want to remove links to “utility” predicates, such as maplist/3 or select/3.

(For myself, I haven’t found much use for graphic tools … if the program is well-structured, the graph doesn’t add much; if it’s not well-structured, the graph is a mess)

---

<div class="post-metadata">

**Author:** ![edmcman](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/edmcman/32/1712_2.png) [@edmcman](https://swi-prolog.discourse.group/u/edmcman)\
**Post date:** [November 30, 2022, 7:27pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/18 "2022-11-30T19:27:51Z")

</div>

My case is probably very unusual. The application is a reverse engineering system that applies many interconnected rules. The rules are dictated by the system being reverse engineered and so are not “well structured”.

I’ve been trying to identify cycles of negations, ala well-founded semantics, to better understand where the system is not well defined.

Here is the graph I produced, in case anyone is curious. It’s already quite simplified.

![g](https://global.discourse-cdn.com/free1/uploads/swiprolog/original/2X/0/0483ad742328191d3c8e65148fc468c9b5fae6ce.svg)

Each edge indicates a negative dependence, i.e., an edge from A to B might be caused by `A :- not(B).`

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [November 30, 2022, 7:58pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/19 "2022-11-30T19:58:10Z")

</div>

> [@edmcman](#):
>
> I’ve been trying to identify cycles of negations, ala well-founded semantics, to better understand where the system is not well defined.

Can you point to a paper(s) or blog(s) that explain those terms i.e. `well-founded semantics` in more detail, in particular when I read `well defined` I am thinking the code is expected to halt, there are no competing locks, the results are of a specific type, etc.

* * *

While I have not used [sCASP](https://github.com/SWI-Prolog/sCASP) I have to wonder if that might not be of use to your problem.

---

<div class="post-metadata">

**Author:** ![edmcman](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/edmcman/32/1712_2.png) [@edmcman](https://swi-prolog.discourse.group/u/edmcman)\
**Post date:** [November 30, 2022, 8:23pm UTC](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978/20 "2022-11-30T20:23:04Z")

</div>

[Well-Founded Semantics](https://www.swi-prolog.org/pldoc/man?section=WFS#:~:text=Well%20Founded%20Semantics%20(WFS)%20defines,%2DProlog%20uses%20undefined%2F0.)

I would say very informally that well defined indicates whether there is an unambiguous solution for the predicates as a result of negation.

I am completely unfamiliar with ASP. But the first example is quite intriguing, and seems similar to WFS:

```prolog
p(A) :- not q(A).
q(A) :- not p(A).
?- p(A).
...
Answer 1	(in 0.09 ms):
p(A) , not q(A)

 ? ;

```

Whereas WFS describes the solution space, maybe ASP enumerates it?

I’ll have to read up more on ASP. Thank you for the link.

[Next page](https://swi-prolog.discourse.group/t/swi-dependency-graph/5978.md?page=2)
