4

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.

4
  • 1
    It is not clear what the requirements are: when typesetting (A,B) would you like all the nodes in the set A to be vertically aligned and similarly for B on a column on the right? Shall they expand radially around the "center" of the edge? Do you need the shape of the edge to respect geometric constraints like "all branches of equal length"? If you were to position the whole cluster a-b-c, where would you want the anchor to be?
    – Bordaigorl
    Oct 7, 2013 at 10:51
  • @Bordaigorl Updated my question to clarify the requirements. Let me know if it's still unclear. Thanks.
    – Roly
    Oct 7, 2013 at 11:15
  • 1
    I'd use TikZ-matrices to place nodes for this. Oct 7, 2013 at 11:38
  • Could you give a simple example of how I would use matrices for this? It seems like this might be preferable to the answer below with explicit polar coordinates.
    – Roly
    Oct 7, 2013 at 12:27

2 Answers 2

3

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.

8
  • Thanks a lot. This seems like an improvement on your earlier suggestion. I'm currently trying out a solution with matrices, as this may give me the right level of flexibility with the angles always implied by the node placement.
    – Roly
    Oct 7, 2013 at 12:46
  • Ok, I've had a chance to play with your example and compare it with matrices. I prefer your approach! There's just one problem: if I change the text associated with a node to be a word rather than a single character, that detrimentally affects the drawing of the hyperedge. To see this, try replacing {g} by {variable}. This happens even if I move the node to the right so that there is plenty of room for the longer name.
    – Roly
    Oct 7, 2013 at 14:00
  • Clarified in my question that I want to have node labels longer than the single characters shown in my example figures.
    – Roly
    Oct 7, 2013 at 14:03
  • It seems this problem can be alleviated through judicious use of anchors. I'll accept this answer if you can update your solution to accommodate longer labels. (I guess it would be reasonable to split \hyperedge' into \mergeedge` and `\splitedge', if that would help, given that we're dealing with directed graphs.)
    – Roly
    Oct 7, 2013 at 14:08
  • I updated the answer. The problem was that the "centre" of the hyperedge was calculated from the center of the lonely node, and not from its border. Using an anchor it can be made to work (maybe there are smarted solutions)
    – Bordaigorl
    Oct 7, 2013 at 14:11
1

This simple example should get you started

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[
    every edge/.append style={thick}
]

\coordinate (e1) at (0,0);

\path (e1) (130:1) node[circle] (a) {a};
\path (e1) (230:1) node[circle] (b) {b};
\path (e1) (0:.8) node[circle] (c) {c};

\draw (e1) edge (a) edge (b) edge (c);

\end{tikzpicture}

\end{document}

Here I choose to position the hyper-edge (e1) first and position the nodes relative to it by using \path then moving to the coordinate of the edge (e1) than moving somewhere from there and placing a node. The coordinates (angle:radius) are polar, the ones (x,y) are cartesian.

The actual "branches" of the hyper-edge are drawn by the \draw command using the edge action which uses the first node as the starting point and connects all the others to it.

Adding other parts of the graph should be easy using these building blocks. Since you seem to want rather precise control on the positioning of the nodes/edges I am not attempting at anything more general/automatic.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .