38

What is the proper way to draw a hypergraph? Is there a package to do this, or is there an easy way to draw such diagrams with a common drawing method like tikz?

I'm trying to draw something like

alt text

3 Answers 3

45

It is -- of course -- posible to draw diagrams like this with TikZ. However, as far as I know there is no automatic placement for things like this.

Once one gets the hang of guessing distances, it is fairly easy to reproduce graph like the example in TikZ:

\usepackage{tikz}
\usetikzlibrary{topaths,calc}

\begin{tikzpicture}
    \node (v1) at (0,2) {};
    \node (v2) at (1.5,3) {};
    \node (v3) at (4,2.5) {};
    \node (v4) at (0,0) {};
    \node (v5) at (2,0.5) {};
    \node (v6) at (3.5,0) {};
    \node (v7) at (2.5,-1) {};

    \begin{scope}[fill opacity=0.8]
    \filldraw[fill=yellow!70] ($(v1)+(-0.5,0)$) 
        to[out=90,in=180] ($(v2) + (0,0.5)$) 
        to[out=0,in=90] ($(v3) + (1,0)$)
        to[out=270,in=0] ($(v2) + (1,-0.8)$)
        to[out=180,in=270] ($(v1)+(-0.5,0)$);
    \filldraw[fill=blue!70] ($(v4)+(-0.5,0.2)$)
        to[out=90,in=180] ($(v4)+(0,1)$)
        to[out=0,in=90] ($(v4)+(0.6,0.3)$)
        to[out=270,in=0] ($(v4)+(0,-0.6)$)
        to[out=180,in=270] ($(v4)+(-0.5,0.2)$);
    \filldraw[fill=green!80] ($(v5)+(-0.5,0)$)
        to[out=90,in=225] ($(v3)+(-0.5,-1)$)
        to[out=45,in=270] ($(v3)+(-0.7,0)$)
        to[out=90,in=180] ($(v3)+(0,0.5)$)
        to[out=0,in=90] ($(v3)+(0.7,0)$)
        to[out=270,in=90] ($(v3)+(-0.3,-1.8)$)
        to[out=270,in=90] ($(v6)+(0.5,-0.3)$)
        to[out=270,in=270] ($(v5)+(-0.5,0)$);
    \filldraw[fill=red!70] ($(v2)+(-0.5,-0.2)$) 
        to[out=90,in=180] ($(v2) + (0.2,0.4)$) 
        to[out=0,in=180] ($(v3) + (0,0.3)$)
        to[out=0,in=90] ($(v3) + (0.3,-0.1)$)
        to[out=270,in=0] ($(v3) + (0,-0.3)$)
        to[out=180,in=0] ($(v3) + (-1.3,0)$)
        to[out=180,in=270] ($(v2)+(-0.5,-0.2)$);
    \end{scope}


    \foreach \v in {1,2,...,7} {
        \fill (v\v) circle (0.1);
    }

    \fill (v1) circle (0.1) node [right] {$v_1$};
    \fill (v2) circle (0.1) node [below left] {$v_2$};
    \fill (v3) circle (0.1) node [left] {$v_3$};
    \fill (v4) circle (0.1) node [below] {$v_4$};
    \fill (v5) circle (0.1) node [below right] {$v_5$};
    \fill (v6) circle (0.1) node [below left] {$v_6$};
    \fill (v7) circle (0.1) node [below right] {$v_7$};

    \node at (0.2,2.8) {$e_1$};
    \node at (2.3,3) {$e_2$};
    \node at (3,0.8) {$e_3$};
    \node at (0.1,0.7) {$e_4$};
\end{tikzpicture}

I think the code is fairly self-explanatory: First the vertice coordinates are specified. Then all the areas are drawn with the help of curve to statements. Afterwards the circles and labels are placed. The result is

picture of a hypergraph

This is not a perfect copy of the original image. With some more fiddling around with the coordinates and some additional points in the paths one could get closer.

1
  • 1
    That's amazing. Nice.
    – Neil G
    Commented Aug 11, 2010 at 22:21
32

I have to confess myself not particularly enamored of the example given: it looks messy to me. I find it hard to separate the edge labels from the vertex labels, and the extra wiggliness of the edges is there for no good reason. I would imagine that for it to be worth drawing such a diagram, it cannot be too complicated (imagine drawing the hypergraph corresponding to the powerset of even 3 elements). So here's an attempt at making a cleaner diagram. Again, it uses TikZ, but by making the diagram more stylised, I can get away with some tricks. In particular, note that the edges are done by drawing really thick lines between the vertices.

\documentclass{article}
\pagestyle{empty}
\usepackage{tikz}

\tikzstyle{vertex} = [fill,shape=circle,node distance=80pt]
\tikzstyle{edge} = [fill,opacity=.5,fill opacity=.5,line cap=round, line join=round, line width=50pt]
\tikzstyle{elabel} =  [fill,shape=circle,node distance=30pt]

\pgfdeclarelayer{background}
\pgfsetlayers{background,main}

\begin{document}
\begin{tikzpicture}
\node[vertex,label=above:\(v_1\)] (v1) {};
\node[vertex,right of=v1,label=above:\(v_2\)] (v2) {};
\node[vertex,right of=v2,label=above:\(v_3\)] (v3) {};
\node[vertex,below of=v1,label=above:\(v_4\)] (v4) {};
\node[vertex,right of=v4,label=above:\(v_5\)] (v5) {};
\node[vertex,right of=v5,label=above:\(v_6\)] (v6) {};
\node[vertex,below of=v5,label=above:\(v_7\)] (v7) {};

\begin{pgfonlayer}{background}
\draw[edge,color=yellow] (v1) -- (v2) -- (v3);
\begin{scope}[transparency group,opacity=.5]
\draw[edge,opacity=1,color=green] (v3) -- (v5) -- (v6) -- (v3);
\fill[edge,opacity=1,color=green] (v3.center) -- (v5.center) -- (v6.center) -- (v3.center);
\end{scope}
\draw[edge,color=red,line width=40pt] (v2) -- (v3);
\draw[edge,color=purple] (v4) -- (v4);
\end{pgfonlayer}

\node[elabel,color=yellow,label=right:\(e_1\)]  (e1) at (-3,0) {};
\node[elabel,below of=e1,color=red,label=right:\(e_2\)]  (e2) {};
\node[elabel,below of=e2,color=green,label=right:\(e_3\)]  (e3) {};
\node[elabel,below of=e3,color=purple,label=right:\(e_4\)]  (e4) {};
\end{tikzpicture}
\end{document}

Here's the picture:

hypergraph

For more complicated graphs, I would see if I could get graphviz or something like that to generate it, and then get TikZ to render it.

6
  • Your webserver seems to have a problem.
    – Caramdir
    Commented Aug 6, 2010 at 11:03
  • For non-mathematicians, could someone give a hint as to the standard 'style' of these things? I like the order in Andrew's approach, but wonder if this is what is expected.
    – Joseph Wright
    Commented Aug 6, 2010 at 11:15
  • @Caramdir: Yeah, power cut. Unfortunately, my open-id is hosted there as well so I couldn't log on here. Seems to be back now. @Joseph Wright: I've never heard of a 'hypergraph' before, but it's not my area. The Wikipedia page suggests a couple of ways of representing one; I would prefer drawing it like an ordinary graph with some vertices "verticies" and others "edges" (see near bottom of Wikipedia page). Then one could use graphviz to design it and TikZ to render it. Commented Aug 6, 2010 at 12:23
  • 2
    Not my area either but the problem of drawing graphs is apparently difficult enough to merit at least 18 "International Symposia on Graph Drawing" (graphdrawing.org)
    – Caramdir
    Commented Aug 6, 2010 at 13:01
  • 1
    I'm not sure what is the standard style for hypergraphs, but this looks like a great representation for the hypergraph -- much more readable. Thanks a lot!
    – Moor Xu
    Commented Aug 6, 2010 at 22:03
6

The answer combines the two great answers by Dr. Clemens Koppensteiner and Andrew Stacey respectively with a little modification. Now the figure puts a clear list of edge labels on the left-hand side of the hypergraph, with the same graphic style from the Wikipedia entry mentioned in the question. Besides, I did not find the command \usetikzlibrary{topaths} necessary here, so I just removed it.

It is compiled successfully with pdfTeX 3.14159265-2.6-1.40.20 (TeX Live 2019/Debian) on Kubuntu 20.04.2 LTS. Here is the MME:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}
    \begin{tikzpicture}
        \node (v1) at (0, 2) {};
        \node (v2) at (1.5, 3) {};
        \node (v3) at (4, 2.5) {};
        \node (v4) at (0, 0) {};
        \node (v5) at (2, 0.5) {};
        \node (v6) at (3.5, 0) {};
        \node (v7) at (5, 0) {};

        \begin{scope}[fill opacity = 0.8]
            \filldraw [fill = yellow!70] ($(v1) + (-0.5, 0)$)
            to [out = 90, in = 180] ($(v2) + (0, 0.5)$)
            to [out = 0,in = 90] ($(v3) + (1, 0)$)
            to [out = 270, in = 0] ($(v2) + (1, -0.8)$)
            to [out = 180, in = 270] ($(v1) + (-0.5, 0)$);
            \filldraw [fill = blue!70] ($(v4) + (-0.5, 0.2)$)
            to [out = 90, in = 180] ($(v4) + (0, 1)$)
            to [out = 0, in = 90] ($(v4) + (0.6, 0.3)$)
            to [out = 270, in = 0] ($(v4) + (0, -0.6)$)
            to [out = 180, in = 270] ($(v4) + (-0.5, 0.2)$);
            \filldraw [fill = green!70] ($(v5) + (-0.5, 0)$)
            to [out = 90, in = 225] ($(v3) + (-0.5, -1)$)
            to [out = 45, in = 270] ($(v3) + (-0.7, 0)$)
            to [out = 90, in = 180] ($(v3) + (0, 0.5)$)
            to [out = 0, in = 90] ($(v3) + (0.7, 0)$)
            to [out = 270, in = 90] ($(v3) + (-0.3, -1.8)$)
            to [out = 270, in = 90] ($(v6) + (0.5, -0.3)$)
            to [out = 270, in = 270] ($(v5) + (-0.5, 0)$);
            \filldraw [fill = red!70] ($(v2) + (-0.5, -0.2)$)
            to [out = 90, in = 180] ($(v2) + (0.2, 0.4)$)
            to [out = 0, in = 180] ($(v3) + (0, 0.3)$)
            to [out = 0, in = 90] ($(v3) + (0.3, -0.1)$)
            to [out = 270, in = 0] ($(v3) + (0, -0.3)$)
            to [out = 180, in = 0] ($(v3) + (-1.3, 0)$)
            to [out = 180, in = 270] ($(v2) + (-0.5, -0.2)$);
        \end{scope}

        \foreach \i in {1, 2, ..., 7}
        {
            \fill (v\i) circle (0.1);
        }

        \fill (v1) circle (0.1) node [right] {$v_1$};
        \fill (v2) circle (0.1) node [below right] {$v_2$};
        \fill (v3) circle (0.1) node [left] {$v_3$};
        \fill (v4) circle (0.1) node [below] {$v_4$};
        \fill (v5) circle (0.1) node [below right] {$v_5$};
        \fill (v6) circle (0.1) node [below left] {$v_6$};
        \fill (v7) circle (0.1) node [below right] {$v_7$};

        \begin{scope}[every node/.style = {fill, shape = circle, node distance = 30pt}]
            \node (e1) [color = yellow!56, label = right:$e_1$] at (-3, 3) {};
            \node (e2) [below of = e1, color = red!56, label = right:$e_2$] {};
            \node (e3) [below of = e2, color = green!56, label = right:$e_3$] {};
            \node (e4) [below of = e3, color = blue!56, label = right:$e_4$] {};
        \end{scope}
    \end{tikzpicture}
\end{document}

And the generated figure is displayed below: The hypergraph

2
  • 1
    Welcome to TeX.SE!
    – Mensch
    Commented Mar 22, 2021 at 17:02
  • @Mensch Thank you! Commented Mar 22, 2021 at 19:20

You must log in to answer this question.

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