Thank you very much @steveroush!
Apologies for this late reply, I got sidetracked. I’ll try to provide some additional context and then address each of your points.
I should clarify an important point about the three kinds of graphs that I am considering. To start, the software package RxInfer.jl: https://rxinfer.ml/ uses “reactive message passing” to instantiate a paradigm for approximate Bayesian Inference. This kind of message passing is analytically described on a Forney-style factor graph (FFG). There are usually constraints of one kind or another to consider, hence one usually talks of “constrained” Forney-style factor graphs: (CFFG). In both cases, FFGs and CFFGs are used to describe the analytic message-passing procedure. This is what one sees in almost all papers on the subject. Indeed, the following two papers provide a relatively comprehensive overview of what these two kinds of graphs are, and how one would go about conducting the message passing procedure: [2306.08014] Realising Synthetic Active Inference Agents, Part I: Epistemic Objectives and Graphical Specification Language and [2306.02733] Realising Synthetic Active Inference Agents, Part II: Variational Message Updates.
Here’s the rub… RxInfer.jl itself does not actually instantiate or use FFGs or CFFGs. The message passing procedure is actually carried out on a “plain old” factor graph. Again, a “raw” factor graph is just a bipartite graph. The two node sets are factor nodes and variable nodes, respectively. Nevertheless, the message-passing procedure is formally (abstractly) equivalent in the respective cases that either use a “raw” factor graph or an FFG/CFFG.
Given these considerations, my collaborators and I want to build visualization capabilities for the “raw”, FFG and CFFG models. Again, only the “raw” model actually exists in memory, the equivalent FFG/CFFG is “merely” a nice mathematical abstraction. To simplify things, we have decided to break the project down into three stages: “Raw model”, “FFG” and “CFFG”. At present, we only care about visualizing the raw/plain model.
I have already built the initial functionality to create a GraphViz graph from an RxInfer model. Indeed, the following is a simple example of a coin-toss model - designed to infer the (unknown) bias of the coin:
Instantiating this model in RxInfer, we have:
This has created the above model and conditioned the model on three data points or “flips” of the coin. For context, the “gppl_model” is the underlying “raw” factor graph.
Using the existing visualization functionality, we can plot the graph with GraphPlot:
Now I have written a function called “generate_dot”, which takes in the raw model - gppl_model - and outputs the associated DOT code as a Julia string. I then have another function called “show_gv” which executes this DOT string and consequently constructs the GraphViz visualization. Here is what it looks like with the neato layout:
I’ve made it such that white circles are “variable” nodes and grey squares are “factor” nodes. Here is the same vgraph again, only now with the dot layout:
I find the output of the dot layout to be undesirable. The neato spring-style layout is very much what we would like to go for, regarding the raw model. In any case, we would ultimately like to be able to write a custom layout for the raw model.
Indeed, neato seems to be fine for our initial contribution, however it seems to run into trouble for larger model graphs. Here is the result of a neato layout for a much larger graph, for a completely different model - note that this graph is cyclic, that’s probably relevant somehow…
It’s too big to see all at once, but some of the nodes clearly overlap in undesirable ways. I have tried to manipulate everything that I can but I can’t seem to stop some of the nodes from overlapping. This is one of the reasons that I think it would be best to go for a custom layout.
Your comments about a “postprocessor pipeline” intrigue me. Perhaps that could be used to address the overlap issues I seem to be having with neato? Perhaps neato -n is best for this, I can’t believe that I missed that option!
In any case, I do want to be able to write a custom layout engine for our use case. The means of getting started on that are completely opaque to me now, I didn’t find the associated documentation page to be all that helpful. I should note that we are also going to be using TikZ for this project. Indeed, TikZ is best for creating “paper-ready” visualizations, however we also really like GraphViz and we want to continue with it.
Insofar as any of the above constitutes an “actual question”, I’m interested in anyone’s thoughts regarding how to avoid the overlaps that vanilla neato seems to produce. I’m also eager to hear any other comments/suggestions of any other kind!
Lastly, this recent presentation here introduces RxInfer.jl and all the associated ideas that I have mentioned here: https://www.youtube.com/watch?v=KuluqEzFtm8. There are even three videos with one of the authors of the above papers: https://www.youtube.com/watch?v=nuUWmwrz6cI and: https://www.youtube.com/watch?v=YNsUMgOQYpk and finally: https://www.youtube.com/watch?v=N7QSuazEEhE. I figure it’s best to give more context than less just now.
Many thanks again @steveroush and thank you for your time.
Fraser