# Help with Graph Consisting of Lines and Nodes

I am trying to draw the following graph in tikz, but rather embarrasingly, I have only managed to draw part (a).

I tried to read the extensive pgfmanual and was intimidated and bewildered by the immensity of work required to draw a simple-looking graph as above; pages 416-532! Here is the code I toiled to extract and modified a bit with the meager outcome of (a). Could somebody please help me as to how I should produce the two other graphs or introduce a manual with which preferably a seizure is to be avoided.

\tikz { \graph[nodes={circle, inner sep=0pt, minimum size=2mm, fill, as=}]{ a -- b}}

• Can you provide a more descriptive title for your post?
– Werner
Commented Feb 5, 2023 at 5:48
• @Werner I gave it a try. Commented Feb 6, 2023 at 15:27

Tikz can be quite overwhelming at first. I'm offering you a solution which may not be the most elegant (from the point of view of a coder) but is geometrically easy to understand.

• Filldraw is used to draw points, and draw is used to draw lines between two points. Those are basic commands.
• I use the shapes.geometric library which is very helpful to create regular polygones. Also I can refer to each corner of the polygon very easily (and I name their coordinates so they are easier to recognize).
• The other one is calc, which is used to calculate with coordenates (in this case the middle point between two other points).
\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,calc}

\begin{document}

\begin{tikzpicture}
\node[thick,regular polygon,regular polygon sides=5, minimum size=4cm,draw] (poli) at (0,0) {};

\coordinate (v1) at (poli.corner 2);
\coordinate (v2) at (poli.corner 3);
\coordinate (v3) at (poli.corner 4);
\coordinate (v4) at (poli.corner 5);
\coordinate (v5) at (poli.corner 1);

\filldraw (v1) node[left]{$v_1$} circle (2pt);
\filldraw (v2) node[left]{$v_2$} circle (2pt);
\filldraw (v3) node[right]{$v_3$} circle (2pt);
\filldraw (v4) node[right]{$v_4$} circle (2pt);
\filldraw (v5) node[above]{$v_5$} circle (2pt);

\draw (v1) -- (v3)
(v1) -- (v4)
(v2) -- (v4)
(v2) -- (v5)
(v3) -- (v5);

\coordinate (u1) at ($0.5*(v2)+0.5*(v5)$);
\coordinate (u2) at ($0.5*(v1)+0.5*(v3)$);
\coordinate (u3) at ($0.5*(v2)+0.5*(v4)$);
\coordinate (u4) at ($0.5*(v3)+0.5*(v5)$);
\coordinate (u5) at ($0.5*(v1)+0.5*(v4)$);
\coordinate (w) at (poli.center);

\filldraw (u1) node[left]{$u_1$} circle (2pt);
\filldraw (u2) node[left]{$u_2$} circle (2pt);
\filldraw (u3) node[right]{$u_3$} circle (2pt);
\filldraw (u4) node[right]{$u_4$} circle (2pt);
\filldraw (u5) node[above]{$u_5$} circle (2pt);
\filldraw (w) node[right]{$w$} circle (2pt);

\draw (u1) -- (w)
(u2) -- (w)
(u3) -- (w)
(u4) -- (w)
(u5) -- (w);

\end{tikzpicture}
\end{document}


This is the result:

Since you already have a tikz solution, I am adding a MetaFun one. I do not know how to translate it into tikz, but maybe you get an idea (or somebody else can make use of it). I only do the third one, since the middle one is probably easy to do if one knows how to do it.

\startMPpage[offset=1dk]
u := 4cm ;

path p ; p := for i = 0 upto 4 : (0,u) rotatedaround(origin, 72*i) -- endfor cycle ;
draw p withpen pencircle scaled 1 ;

for i = 0 upto 4 :
draw (point i of p) -- (point i + 2 of p) withcolor darkyellow ;
draw (origin -- 0.5[point i of p, point i+2 of p]) withcolor darkred ;
drawdot point i of p withstacking 2 withpen pencircle scaled 4 withcolor darkgreen ;
drawdot 0.5[point i of p, point i+2 of p] withstacking 2 withpen pencircle scaled 4 withcolor darkblue ;
endfor

for i = 1 upto 5 :
freelabel("$v_{" & decimal i & "}$", point i of p, origin ) ;
freelabel("$u_{" & decimal i & "}$", 0.5[point i-1 of p, point i+1 of p], origin ) ;
endfor

drawdot origin withstacking 2 withpen pencircle scaled 4 ;
label.rt("$w_4$", (0.05u,-0.05u) ) ;
\stopMPpage


Running context on this file gives the following:

I added some colors just to make it easier to see what is what. That also lead to some ordering issue, solved by adding the dots in another layer (with withstacking). The last label was placed with a bit of trial and error.

• +1 MetaFun means that this only compiles with ConText, right? Commented Feb 6, 2023 at 16:37
• I have not tried it outside of ConTeXt, but maybe it works with input metafun.mp ;. Commented Feb 6, 2023 at 16:40
• You can also use it with lualatex and luamplib with the option \mplibsetformat{metafun} Commented Jul 16, 2023 at 21:41

A \foreach based solution in plain TikZ, no libraries needed. First we place the coordinates and them we draw all.

\documentclass[tikz,border=2mm]{standalone}
% the vertex at \y places from \x vertex
% example nextvertex(4,2) = 1 --> ...,4,5,1,...
\tikzset{declare function={nextvertex(\x,\y)=int(mod(\x+\y-1,5)+1);}}

\begin{document}
\begin{tikzpicture}
\foreach\i in {1,...,5} % coordinates
\path (0,0) -- (90+72*\i:{2*sin(18)}) coordinate (u\i) node[pos=1.35] {$u_\i$}
-- (90+72*\i:2)           coordinate (v\i) node[pos=1.15] {$v_\i$};
\foreach\i in {1,...,5}
{% lines and points
\pgfmathtruncatemacro\j{nextvertex(\i,1)}
\pgfmathtruncatemacro\k{nextvertex(\i,2)}
\draw[thick] (v\i) -- (v\j);
\draw        (v\i) -- (v\k);
\draw        (0,0) -- (u\i);
\fill        (v\i) circle (1pt);
\fill        (u\i) circle (1pt);
}
\end{tikzpicture}
\end{document}


Here's a version in plain Metapost, purely for comparison.

This is done with the luamplib package, so you need to compile it with lualatex.

\documentclass[border=5mm]{standalone}
\usepackage{cmbright}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
beginfig(1);
picture P[];
P1 = image(
path a; a = (left -- right) scaled 34;
draw a;
draw point 0 of a withpen pencircle scaled dotlabeldiam;
draw point 1 of a withpen pencircle scaled dotlabeldiam;
label.bot("(a)", 55 down);
);

P2 = image(
path p; p = for t = 0 upto 4: 34 up rotated 72t -- endfor cycle;
draw p;
for t = 0 upto 4: draw point t of p withpen pencircle scaled dotlabeldiam; endfor
label("$v_1$", point 1 of p shifted 7 unitvector(point 1 of p));
label("$v_2$", point 2 of p shifted 7 unitvector(point 2 of p));
label("$u_1$", point 3 of p shifted 7 unitvector(point 3 of p));
label("$w_3$", point 4 of p shifted 8 unitvector(point 4 of p));
label("$u_2$", point 5 of p shifted 6 unitvector(point 5 of p));
label.bot("(b)", 55 down);
);

P3 = image(
pair u[], v[];
for i = 0 upto 6: v[i] = 78 up rotated 72i; endfor
for i = 1 upto 5: u[i] = whatever * v[i] = whatever[v[i+1], v[i-1]]; endfor

draw for i = 1,2,3,4,5: v[i] -- endfor cycle;
draw for i = 1,3,5,2,4: v[i] -- endfor cycle withpen pencircle scaled 1/4;

for i = 1 upto 5:
draw origin -- u[i] withpen pencircle scaled 1/4;
draw u[i] withpen pencircle scaled dotlabeldiam;
draw v[i] withpen pencircle scaled dotlabeldiam;
label("$u_" & decimal i & "$", u[i] shifted 7 unitvector(u[i]));
label("$v_" & decimal i & "$", v[i] shifted 7 unitvector(v[i]));
endfor
draw origin withpen pencircle scaled dotlabeldiam;
label("$w_4$", 11 dir -20);
label.bot("(c)", 89 down);
);

draw P1;
draw P2 shifted 124 right;
draw P3 shifted 290 right;

endfig;
\end{mplibcode}
\end{document}


## Notes

• The OP image has sans-serif labels, so I added them here too. If you prefer the default fonts, just remove the \usepackage{cmbright} line.

• The overall structure here is that I have used the image macro to create three independent drawings as <picture> variables, P1, P2, and P3. Then I have drawn them next to each other to make the final image. The "reference point" of each <picture> is the origin, point (0, 0), so drawn like this, the origin points in each picture line up horizontally. But you can also pass a <picture> to the label macro, so you could do this:

  label.top(P1, origin);
label.top(P2, 124 right);
label.top(P3, 290 right);


to get them lined up like this:

• The usual way to make labels with dots is to use the dotlabel command, but in this drawing I needed more flexibility in placing the text relative to the dots, so I have separated drawing the dot and placing the label. To draw a dot at point p, you can use

  draw p withpen pencircle scaled dotlabeldiam;


(or drawdot if you prefer, in MP they are the same). The size dotlabeldiam is defined in the plain format, and is used by the dotlabel macro, so it's neat to borrow it, so that the dots match any you might also draw with dotlabel.

• The p shifted 7 unitvector(p) trick works neatly here because the points are all centred on the origin. If you wanted to use a different centre point, say o, then you could try p shifted 7 unitvector(p-o).

For nice simple approachable tutorials in Metapost, follow the link at the top...

You don't need to use \graph for this, just use the simple \node and \draw:

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[blacknode/.style={fill, circle, minimum size=1mm, inner sep=0pt}]
\node [blacknode] (a) at (0, 0) {};
\node [blacknode] (b) at (1, 1) {};
\draw (a) -- (b);
% add more nodes and edges as needed
\end{tikzpicture}

\end{document}


(or try reading VisualTikZ for a quick reference)

In this case, the graphs are indeed difficult (even if you write a program in a "normal" programming language to compute the coordinates it's quite nontrivial)...

I cheat a bit by using GeoGebra to compute the relevant distances (the angles are obviously multiples of 72 degrees):

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[blacknode/.style={fill, circle, minimum size=1mm, inner sep=0pt}, labelnode/.style={font=\tiny}]
\def\largeLength{1.7013}
\def\smallLength{0.52573}
\path
(0, 0)                  node [blacknode] (w4) {} node [labelnode, above] {w4}
(90:\smallLength)       node [blacknode] (u5) {} node [labelnode, above] {u5}
(90+72:\smallLength)    node [blacknode] (u1) {} node [labelnode, above] {u1}
(90+72*2:\smallLength)  node [blacknode] (u2) {} node [labelnode, above] {u2}
(90+72*3:\smallLength)  node [blacknode] (u3) {} node [labelnode, above] {u3}
(90+72*4:\smallLength)  node [blacknode] (u4) {} node [labelnode, above] {u4}
(90:\largeLength)       node [blacknode] (v5) {} node [labelnode, above] {v5}
(90+72:\largeLength)    node [blacknode] (v1) {} node [labelnode, above] {v1}
(90+72*2:\largeLength)  node [blacknode] (v2) {} node [labelnode, below] {v2}
(90+72*3:\largeLength)  node [blacknode] (v3) {} node [labelnode, below] {v3}
(90+72*4:\largeLength)  node [blacknode] (v4) {} node [labelnode, above] {v4}
;
\draw [thick] (v1) -- (v2) -- (v3) -- (v4) -- (v5) -- (v1);  % I don't know why "cycle" doesn't work here but anyway
\draw (v1) -- (v4) -- (v2) -- (v5) -- (v3) -- (v1);
\draw (w4) -- (u1);
\draw (w4) -- (u2);
\draw (w4) -- (u3);
\draw (w4) -- (u4);
\draw (w4) -- (u5);
\end{tikzpicture}

\end{document}


It needs some manual work to tweak the positions of the labels however.

Whenever you are looking to do something easier, go to CTAN and search: in this case, for "graph". You'll get lots of results. I'm using tkz-graph and tkz-berge packages. Next, the more you know about the graph, the easier it is. The first graph is a path on 2 vertices, the second is a cycle on 4 vertices, and the third is the Grotzsch graph. Knowing the name will let you take shortcuts which can save you lots of time in creating the graph. The Altermundus site, which is behind tkz-berge and several other useful packages, has created a gallery of named graphs which is a PDF that you can download specifying graphs that have are already built in. The first of 3 forms of the Grotzsch graph is on page 51 and it is closest to your graph. The problem is, the creation uses a different set of vertex labels than you are using. To get around this, I'm using the information in the answer to the question Label only selected vertices with tkz-berge to modify that graph to make it more like yours with the code below:

\documentclass[11pt]{article}
\usepackage{sagetex,tkz-graph,tkz-berge}
\begin{document}
\begin{tikzpicture}[every label/.append style={font=\Large}]
\GraphInit[vstyle=Classic]
\SetVertexNoLabel
\grGrotzsch[RA=3,RB=6]{6}%
\SetVertexLabel
\Vertex[Node,Lpos=45,L=$u_4$]{a0}
\Vertex[Node,Lpos=90,L=$u_5$]{a1}
\Vertex[Node,Lpos=180,L=$u_1$]{a2}
\Vertex[Node,Lpos=270,L=$u_2$]{a3}
\Vertex[Node,Lpos=270,L=$u_3$]{a4}
\Vertex[Node,Lpos=-3,L=$w_4$]{a5}
\Vertex[Node,Lpos=0,L=$v_4$]{b0}
\Vertex[Node,Lpos=90,L=$v_5$]{b1}
\Vertex[Node,Lpos=180,L=$v_1$]{b2}
\Vertex[Node,Lpos=270,L=$v_2$]{b3}
\Vertex[Node,Lpos=270,L=$v_3$]{b4}
\end{tikzpicture}
\end{document}


The result, running in Gummi is below:

Note that the command \Vertex[Node,Lpos=45,L=$u_4$]{a0} is using the label $u_4$ for the node which was a0. The position of the label Lpos=0 degrees if you want the label to the right of the vertex, and Lpos=45 rotates it counterclockwise 45 degrees so you can put the label where you'd like it. The documentation explains how you can change the style of the labels as well as vertices (for example making the vertices smaller) and edges.

If there is no name to your graph then you have to specify the coordinates and labels such as was done in my answer here. Note that this answers shows you can combine it with the open source CAS, called Sage. It has a lot of graphs that it knows on this page. See my answer to the closed question here on an easy way to generate the Hoffman Singleton graph.

• +1: The gallery of named graphs is wonderful! Commented Feb 6, 2023 at 0:02