[Tex/LaTex] Simple directed hypergraphs in TikZ

graphstikz-pgf

I'm looking for a simple way in Tikz to draw directed hypergraphs, where the hyperedges are ordered pairs of sets of vertices. For example I would like the hyperedges ({a,b},{c}) and ({c},{a,b}) to be presented like this:

enter image description here

The "in" vertices (on the left) should be vertically aligned, as should the "out" vertices (on the right). For my purposes, there are never more than two "in" vertices or two "out" vertices, and I would be happy to have this baked into the solution. The solution should be flexible enough to accommodate node labels larger than the single characters shown here.

I would also like to be able to assemble these into larger hypergraphs, as shown here, in which case the arms of the hyperedges need not be of the same length:

enter image description here

although the "direction" will always be read from left to right. I'm not concerned with overlapping lines (I'll only be working with simple graphs and will be able to arrange things so lines don't overlap).

It should be easy to move the nodes around for aesthetic reasons, so that for example the following is the graph above but laid out slightly differently:

enter image description here

The title of this question is similar, but my requirements are slightly different.

Best Answer

A second attempt, this time making some assumptions on the layout. I assume you want the hyper-edge to always be aligned to the "lonely" node of the triplets (e.g. c in ({a,b},{c}) and ({c},{a,b}) ).

Since you seem to need fine control on the positioning of the nodes I suggest the following: first you place named nodes with manual positioning (using whichever method you prefer, from absolute coordinates to relative positioning); then you specify the hyperedges and the corresponding arcs get created. Here's a macro that can help you with the second step:

\newcommand{\hyperedge}[4][180]{
     \draw (#2.#1) ++(#1:.5)  edge (#2) edge (#3) edge (#4);
}

It takes 4 arguments (first optional): \hyperedge[angle]{c}{a}{b} draws the edges assuming that c is the lonely node and requires you to specify the angle at which the hyperedge should stick out of it.

The definition of the macro works by moving to the right/left border of the lonely node (this is accomplished by (#2.#1) which moves to the border of the node #2 at angle #1), then move right/left by .5 which is the coordinate of the "centre" of the edge; then this "centre" is connected with the nodes using the edge action.

Here's your second example using tikz and my macro:

\documentclass{standalone}
\usepackage{tikz}

\newcommand{\hyperedge}[4][180]{
     \draw (#2.#1) ++(#1:.5)  edge (#2) edge (#3) edge (#4);    
}

\begin{document}
\begin{tikzpicture}[
    y=.7cm, x=1cm,
    every edge/.append style={thick}
]

\node (a) at (-1,1) {a};
\node (b) at (-1,-1) {b};
\node (c) at (0,0) {c};
\node (d) at (1,1) {d};
\node (e) at (1,-1) {e};
\node (g) at (2,-2) {g};

\hyperedge{c}{b}{a}
\hyperedge[0]{c}{d}{e}
\hyperedge{g}{b}{e}


\end{tikzpicture}

\end{document}

Which is rather readable and easy to extend.

You can elaborate on this by using other means to specify the angle (other derived macros) or enriching it with custom styles.

Another option for the placement of the "centre" of the hyperedge is barycentric coordinates:

\newcommand{\hyperedge}[3]{
    \draw (barycentric cs:#1=1,#2=1,#3=1) edge (#1) edge (#2) edge (#3);
}

Note that this does not require the angle argument.