7

I want to include accolades in my bipartite graph to show that nodes belong to a certain group. With the code below I created the following bipartite graph:

\begin{figure}[H]
\centering
\definecolor{myblue}{RGB}{80,80,160}
\definecolor{mygreen}{RGB}{80,160,80}
\begin{tikzpicture}[thick,
  every node/.style={draw,circle},
  fsnode/.style={fill=myblue},
  ssnode/.style={fill=mygreen},
  every fit/.style={ellipse,draw,inner sep=-2pt,text width=2cm},
  ->,shorten >= 3pt,shorten <= 3pt
]
% the vertices of P
\begin{scope}[start chain=going below,node distance=10mm]
  \node[fsnode,on chain] (f1) [label=left: $p_{1}$] {};
  \node[fsnode,on chain] (f2) [label=left: $p_{2}$] {};
  \node[fsnode,on chain] (f3) [label=left: ] {};
  \node[fsnode,on chain] (f4) [label=left: $p_{n}$] {};
\end{scope}

% the vertices of L
\begin{scope}[xshift=6cm,yshift=0cm,start chain=going below,node distance=10mm]
  \node[ssnode,on chain] (s1) [label=right: $l_{1}$] {};
  \node[ssnode,on chain] (s2) [label=right: $l_{2}$] {};
  \node[ssnode,on chain] (s3) [label=right: ] {};
  \node[ssnode,on chain] (s4) [label=right: $l_{m}$] {};
\end{scope}

% the set P
\node [myblue,fit=(f1) (f4),label=above:$Products$] {};
% the set L
\node [mygreen,fit=(s1) (s4),label=above:$Locations$] {};
% the edges
\draw[ultra thin,dashed,-] (f2) -- (f3);
\draw[ultra thin,dashed,-] (f3) -- (f4);
\draw[ultra thin,dashed,-] (s2) -- (s3);
\draw[ultra thin,dashed,-] (s3) -- (s4);
\draw[-,dotted] (f1) -- (s1);
\draw[-,dotted] (f1) -- (s2);
\draw[-,dotted] (f1) -- (s3);
\draw[-,dotted] (f1) -- (s4);
\draw[-,dotted] (f2) -- (s1);
\draw[-,dotted] (f2) -- (s2);
\draw[-,dotted] (f2) -- (s3);
\draw[-,dotted] (f2) -- (s4);
\draw[-,dotted] (f3) -- (s1);
\draw[-,dotted] (f3) -- (s2);
\draw[-,dotted] (f3) -- (s3);
\draw[-,dotted] (f3) -- (s4);
\draw[-,dotted] (f4) -- (s1);
\draw[-,dotted] (f4) -- (s2);
\draw[-,dotted] (f4) -- (s3);
\draw[-,dotted] (f4) -- (s4);
\end{tikzpicture}
\end{figure}

This induces the image: enter image description here

But what I would like is the following image: enter image description here

What code do I have to add to make use of accolades or something simular?

1 Answer 1

11

You can use the brace decoration from the decorations.pathreplacing library for that. I used a lot of shifts to make it a bit better looking, but you can choose to omit those. By using the method as explained by @marmot, all the shifts can be omitted.

This is the code for the braces:

    \node[fit={(f1)(f3)(f3-|set1.west)},subset] (c1-fit) {};
    \node[fit={(f4)(f5)(f5-|set1.west)},subset] (c2-fit) {};
    \node[fit={(f7)(f8)(f8-|set1.west)},subset] (c3-fit) {};
    \node[fit={(s1)(s2)(s2-|set2.east)},subset] (lc1-fit) {};
    \node[fit={(s3)(s5)(s5-|set2.east)},subset] (lc2-fit) {};
    \node[fit={(s8)(s8)(s8-|set2.east)},subset,inner ysep=10pt] (lc3-fit) {};

    \begin{scope}[decoration={brace,amplitude=3mm}]
        \begin{scope}[decoration={mirror},every node/.style={midway,left,xshift=-3mm}]
            \draw[decorate] (c1-fit.north west) -- (c1-fit.south west) node(C1){$ C_1 $};
            \draw[decorate] (c2-fit.north west) -- (c2-fit.south west) node(C2){$ C_2 $};
            \draw[decorate] (c3-fit.north west) -- (c3-fit.south west) node(Cg){$ C_\gamma $};
        \end{scope}
        \begin{scope}[every node/.style={midway,right,xshift=3mm}]
            \draw[decorate] (lc1-fit.north east) -- (lc1-fit.south east) node(LC1){$ L^{C_1} $};
            \draw[decorate] (lc2-fit.north east) -- (lc2-fit.south east) node(LC2){$ L^{C_2} $};
            \draw[decorate] (lc3-fit.north east) -- (lc3-fit.south east) node(LCg){$ L^{C_\gamma} $};
        \end{scope}
    \end{scope}

enter image description here

I also used some \foreach loops to ease the drawing of all those similar lines, and to place the circular nodes that don't have a label.

Also I noticed that you set -> for the entire tikzpicture, and then continue to set the - key for all \draw commands, which feels a bit counterproductive so I removed that. Additionally I changed the every node/.style to a base node/.style and used the inheritance of styles to make sure that both the fsnode style and the ssnode style inherit its properties. Finally I changed the font of the two top labels (Products and Locations) to \itshape, instead of typesetting those words in mathmode, because it simply looks better.

MWE:

\documentclass[tikz,margin=2mm]{standalone}

\usetikzlibrary{chains,fit,shapes,decorations.pathreplacing}

\begin{document}
%    \begin{figure}[H]
    \centering
    \definecolor{myblue}{RGB}{80,80,160}
    \definecolor{mygreen}{RGB}{80,160,80}
    \begin{tikzpicture}[thick,
        base node/.style={draw,circle},
        fsnode/.style={base node,fill=myblue},
        ssnode/.style={base node,fill=mygreen},
        set/.style={ellipse,draw,inner xsep = 20pt,inner ysep=-20pt},
        subset/.style={inner sep=3pt},
        shorten >= 3pt,shorten <= 3pt
    ]
        % the vertices of P
        \begin{scope}[start chain=going below,node distance=10mm]
            \node[fsnode,on chain] (f1) [label=left: $p_{1}$] {};
            \node[fsnode,on chain] (f2) [label=left: $p_{2}$] {};
            \foreach \i in {3,...,7}{
                \node[fsnode,on chain] (f\i) {};
            }
            \node[fsnode,on chain] (f8) [label=left: $p_{n}$] {};
        \end{scope}

        % the vertices of L
        \begin{scope}[xshift=6cm,yshift=0cm,start chain=going below,node distance=10mm]
            \node[ssnode,on chain] (s1) [label=right: $l_{1}$] {};
            \node[ssnode,on chain] (s2) [label=right: $l_{2}$] {};
            \foreach \i in {3,...,7}{
                \node[ssnode,on chain] (s\i) {};
            }
            \node[ssnode,on chain] (s8) [label=right: $l_{m}$] {};
        \end{scope}

        % the set P
        \node [set,myblue,fit=(f1) (f8),label={[font=\itshape]above:Products}] (set1) {};
        % the set L
        \node [set,mygreen,fit=(s1) (s8),label={[font=\itshape]above:Locations}] (set2) {};
        % the edges
        \foreach \i [count=\j from 1] in {2,...,8}{
            \draw[thin,dashed] (f\j) -- (f\i);
            \draw[thin,dashed] (s\j) -- (s\i);
        }
        \foreach \i in {1,...,8}{
            \foreach \j in {1,...,8}{
                \draw[dotted] (f\i) -- (s\j);
            }
        }

        \node[fit={(f1)(f3)(f3-|set1.west)},subset] (c1-fit) {};
        \node[fit={(f4)(f5)(f5-|set1.west)},subset] (c2-fit) {};
        \node[fit={(f7)(f8)(f8-|set1.west)},subset] (c3-fit) {};
        \node[fit={(s1)(s2)(s2-|set2.east)},subset] (lc1-fit) {};
        \node[fit={(s3)(s5)(s5-|set2.east)},subset] (lc2-fit) {};
        \node[fit={(s8)(s8)(s8-|set2.east)},subset,inner ysep=10pt] (lc3-fit) {};

        \begin{scope}[decoration={brace,amplitude=3mm}]
            \begin{scope}[decoration={mirror},every node/.style={midway,left,xshift=-3mm}]
                \draw[decorate] (c1-fit.north west) -- (c1-fit.south west) node (C1) {$ C_1 $};
                \draw[decorate] (c2-fit.north west) -- (c2-fit.south west) node (C2) {$ C_2 $};
                \draw[decorate] (c3-fit.north west) -- (c3-fit.south west) node (Cg) {$ C_\gamma $};
            \end{scope}
            \begin{scope}[every node/.style={midway,right,xshift=3mm}]
                \draw[decorate] (lc1-fit.north east) -- (lc1-fit.south east) node (LC1) {$ L^{C_1} $};
                \draw[decorate] (lc2-fit.north east) -- (lc2-fit.south east) node (LC2) {$ L^{C_2} $};
                \draw[decorate] (lc3-fit.north east) -- (lc3-fit.south east) node (LCg) {$ L^{C_\gamma} $};
            \end{scope}
        \end{scope}

        \draw[thin,dashed] (C2) -- (Cg);
        \draw[thin,dashed] (LC2) -- (LCg);
    \end{tikzpicture}
%    \end{figure}
\end{document}

PS: I really like the chains! Perfect for this application.

Edit (@Sebastiano)
One might argue that having the labels of the sets in upright shape is aesthetically more acceptable. I will leave the choice for you.

enter image description here

\documentclass[tikz,margin=2mm]{standalone}

\usetikzlibrary{chains,fit,shapes,decorations.pathreplacing}

\begin{document}
%    \begin{figure}[H]
    \centering
    \definecolor{myblue}{RGB}{80,80,160}
    \definecolor{mygreen}{RGB}{80,160,80}
    \begin{tikzpicture}[thick,
        base node/.style={draw,circle},
        fsnode/.style={base node,fill=myblue},
        ssnode/.style={base node,fill=mygreen},
        set/.style={ellipse,draw,inner xsep = 20pt,inner ysep=-20pt},
        subset/.style={inner sep=3pt},
        shorten >= 3pt,shorten <= 3pt
    ]
        % the vertices of P
        \begin{scope}[start chain=going below,node distance=10mm]
            \node[fsnode,on chain] (f1) [label=left: $p_{1}$] {};
            \node[fsnode,on chain] (f2) [label=left: $p_{2}$] {};
            \foreach \i in {3,...,7}{
                \node[fsnode,on chain] (f\i) {};
            }
            \node[fsnode,on chain] (f8) [label=left: $p_{n}$] {};
        \end{scope}

        % the vertices of L
        \begin{scope}[xshift=6cm,yshift=0cm,start chain=going below,node distance=10mm]
            \node[ssnode,on chain] (s1) [label=right: $l_{1}$] {};
            \node[ssnode,on chain] (s2) [label=right: $l_{2}$] {};
            \foreach \i in {3,...,7}{
                \node[ssnode,on chain] (s\i) {};
            }
            \node[ssnode,on chain] (s8) [label=right: $l_{m}$] {};
        \end{scope}

        % the set P
        \node [set,myblue,fit=(f1) (f8),label=above:Products] (set1) {};
        % the set L
        \node [set,mygreen,fit=(s1) (s8),label=above:Locations] (set2) {};
        % the edges
        \foreach \i [count=\j from 1] in {2,...,8}{
            \draw[thin,dashed] (f\j) -- (f\i);
            \draw[thin,dashed] (s\j) -- (s\i);
        }
        \foreach \i in {1,...,8}{
            \foreach \j in {1,...,8}{
                \draw[dotted] (f\i) -- (s\j);
            }
        }

        \node[fit={(f1)(f3)(f3-|set1.west)},subset] (c1-fit) {};
        \node[fit={(f4)(f5)(f5-|set1.west)},subset] (c2-fit) {};
        \node[fit={(f7)(f8)(f8-|set1.west)},subset] (c3-fit) {};
        \node[fit={(s1)(s2)(s2-|set2.east)},subset] (lc1-fit) {};
        \node[fit={(s3)(s5)(s5-|set2.east)},subset] (lc2-fit) {};
        \node[fit={(s8)(s8)(s8-|set2.east)},subset,inner ysep=10pt] (lc3-fit) {};

        \begin{scope}[decoration={brace,amplitude=3mm}]
            \begin{scope}[decoration={mirror},every node/.style={midway,left,xshift=-3mm}]
                \draw[decorate] (c1-fit.north west) -- (c1-fit.south west) node (C1) {$ C_1 $};
                \draw[decorate] (c2-fit.north west) -- (c2-fit.south west) node (C2) {$ C_2 $};
                \draw[decorate] (c3-fit.north west) -- (c3-fit.south west) node (Cg) {$ C_\gamma $};
            \end{scope}
            \begin{scope}[every node/.style={midway,right,xshift=3mm}]
                \draw[decorate] (lc1-fit.north east) -- (lc1-fit.south east) node (LC1) {$ L^{C_1} $};
                \draw[decorate] (lc2-fit.north east) -- (lc2-fit.south east) node (LC2) {$ L^{C_2} $};
                \draw[decorate] (lc3-fit.north east) -- (lc3-fit.south east) node (LCg) {$ L^{C_\gamma} $};
            \end{scope}
        \end{scope}

        \draw[thin,dashed] (C2) -- (Cg);
        \draw[thin,dashed] (LC2) -- (LCg);
    \end{tikzpicture}
%    \end{figure}
\end{document}
8
  • Wonderful! Upvoted. Can I ask a favour, please? Can you edit your answer, putting the text in roman and not italic? It is better, for my opinion.
    – Sebastiano
    Aug 15, 2018 at 9:54
  • @Sebastiano Do you mean the top labels in (normal) upright shape?
    – Max
    Aug 15, 2018 at 9:56
  • Products and Locations, Max, normal shape exact.
    – Sebastiano
    Aug 15, 2018 at 9:57
  • But you are not that you had to let everyone know :-):-). Aesthetically now it is more beautiful :-).
    – Sebastiano
    Aug 15, 2018 at 10:05
  • 1
    +1, very nice! You could actually use fit also to determine the size of the braces. That is, you could fit the nodes that you want to embrace and also one coordinate on the border fit=(f1) (f3) (f1 -| Fit1), where Fit1 is the blue fit node, and then draw the brace from the fit box south west to north west, say.
    – user121799
    Aug 15, 2018 at 13:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.