A Wolfram Notebook on Vizing’s Theorem: From Proof to Program
Vizing's theorem states that if is a simple undirected graph having maximum degree , then has a proper -edge-coloring. Here, a proper -edge-coloring is a coloring of the edges of from a palette of colors such that no vertex is incident to two or more identically colored edges. Note that at least colors are needed for a proper edge-coloring of , to provide enough distinct colors for edges incident to vertices of maximum degree. Combined with Vizing’s theorem, it follows that the edge-chromatic number of , which equals the minimum such that has a proper -edge-coloring, is either or . In this demonstration, we use the Wolfram Language to turn a proof of Vizing’s theorem into a program for giving any graph a proper -edge-coloring.
G
Δ
G
(Δ+1)
k
G
k
Δ
G
G
k
G
k
Δ
Δ+1
G
(Δ+1)
Let be a simple undirected graph. We proceed by induction on , the number of edges. If , then the theorem trivially holds. Let ; to illustrate the proof and our program, we will set as the complete graph on seven vertices.
G=(V,E)
m
m=0
m>0
G
In[1]:=
graph=CompleteGraph[7]
Out[1]=
Hence we have the following palette of “colors” to choose from...
In[2]:=
colors=Range[Max[VertexDegree[graph]]+1]
Out[2]=
{1,2,3,4,5,6,7}
... and for visualization purposes we'll associate them with the following actual hues.
In[3]:=
colorAssociation=AssociationMap[Function[color,Hue[color/Length[colors]]],colors]
Out[3]=
1,2,3,4,5,6,7
Suppose for each edge , there exists a proper -edge-coloring of the edge-deleted subgraph of . We’ll start out by working with the proper -edge-coloring of below (the other vertices are preemptively named for later convenience).
xy∈E
(Δ+1)
c
G-{xy}
G
(Δ+1)
c
G-{xy}
In[4]:=
partialEdges={yy[2],yy[3],yy[4],yy[5],yy[6],y[2]y[3],y[2]y[4],y[2]y[5],y[2]y[6],y[3]y[4],y[3]y[5],y[3]y[6],y[4]y[5],y[4]y[6],y[5]y[6],xy[2],xy[3],xy[4],xy[5],xy[6]};partialGraph=Graph[partialEdges,VertexLabels"Name",GraphLayout"CircularEmbedding"];partialColoring=AssociationThread[partialEdges{2,4,1,3,5,5,4,7,1,7,1,6,6,3,2,6,3,2,5,4}];SetProperty[partialGraph,{EdgeLabelsNormal[partialColoring],EdgeStyleNormal[Map[colorAssociation,partialColoring]]}]
Out[7]=
We say that color is missing in a vertex with respect to the coloring if for every neighbor of , is not the color assigned by to the edge . Note that if is a proper -edge-coloring of , then every vertex has a missing color with respect to , since each vertex is incident to at most colors.
α∈{1,…,Δ+1}
s∈V
c
t
s
α
c(st)
c
st
c
(Δ+1)
G
c
Δ
We define a fan to be a sequence of neighbors of having the following three properties. First, . Second, is missing in with respect to for all . Third, for some color missing in with respect to , either is also missing in with respect to , or for some .
(y(1),…,y(k))
x
y(1)=y
c(xy(i))
y(i-1)
c
2≤i≤k
β
y(k)
c
β
x
c
c(xy(j))=β
1≤j<k
To define a fan, first associate each neighbor of to .
z
x
c(xz)
In[8]:=
xNeighborColoring=AssociationMap[Function[neighbor,partialColoring[Sort[xneighbor]]],AdjacencyList[partialGraph,x]]
Out[8]=
y[2]6,y[3]3,y[4]2,y[5]5,y[6]4
Next, define a function to find a color missing at a given neighbor of .
x
In[9]:=
missingColor[node_]:=With[{usedCols=Map[partialColoring,IncidenceList[partialGraph,node]]},FirstCase[colors,(color_/;FreeQ[usedCols,color])]]missingColor[y[2]]
Out[10]=
3
Then, define a function to incrementally extend the fan by finding an unused neighbor of such that is a color missing in the previous vertex of the fan with respect to . Also update the available nodes, and keep track of the color too.
z
x
c(xz)
c
In[11]:=
extendFan[{node_,availableNodes_,color_}]:=With[{nextAvailableNodes=Complement[availableNodes,{node}],nextColor=missingColor[node]},{FirstCase[nextAvailableNodes,(avNode_/;xNeighborColoring[avNode]nextColor)],nextAvailableNodes,nextColor}]
Iteratively extend the fan, starting with the vertex y, all neighbors of x available and 0 as the unused dummy color. Keep going until the fan can no longer be extended.
In[12]:=
(fanIncrements=NestWhileList[extendFan,{y,Keys[xNeighborColoring],0},Composition[Not,MissingQ,First]])//MatrixForm
Out[12]//MatrixForm=
y | {y[2],y[3],y[4],y[5],y[6]} | 0 |
y[2] | {y[2],y[3],y[4],y[5],y[6]} | 6 |
y[3] | {y[3],y[4],y[5],y[6]} | 3 |
y[4] | {y[4],y[5],y[6]} | 2 |
y[5] | {y[5],y[6]} | 5 |
y[6] | {y[6]} | 4 |
Missing[NotFound] | {} | 7 |
Extract the nodes and colors of the fan, make a list of the fan edges and finally make special note of the last color in the fan.
β
In[13]:=
({fanNodes,fanColors}=Through[{Composition[Most,First],Composition[Rest,Last]}[Transpose[fanIncrements]]])//MatrixFormfanEdges=Map[Function[node,Sort[xnode]],fanNodes]lastFanCol=Last[fanColors]
To find the Kempe chain, we iteratively apply our function until it can no longer find a new vertex to extend the path.
Here’s what our Kempe chain looks like.
We can put everything together into a single function.
We also define a function for checking if a given edge-coloring is proper.