org.jgrapht.alg.color.ChordalGraphColoring Maven / Gradle / Ivy
The newest version!
/*
* (C) Copyright 2018-2023, by Timofey Chudakov and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* See the CONTRIBUTORS.md file distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the
* GNU Lesser General Public License v2.1 or later
* which is available at
* http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html.
*
* SPDX-License-Identifier: EPL-2.0 OR LGPL-2.1-or-later
*/
package org.jgrapht.alg.color;
import org.jgrapht.*;
import org.jgrapht.alg.cycle.*;
import org.jgrapht.alg.interfaces.*;
import org.jgrapht.traverse.*;
import org.jgrapht.util.*;
import java.util.*;
/**
* Calculates a minimum vertex
* coloring for a chordal graph. A
* chordal graph is a simple graph in which all
* cycles of four or more vertices have
* a chord. A chord is an edge that is
* not part of the cycle but connects two vertices of the cycle.
*
* To compute the vertex coloring, this implementation relies on the {@link ChordalityInspector} to
* compute a
* perfect elimination order.
*
* The vertex coloring for a chordal graph is computed in $\mathcal{O}(|V| + |E|)$ time.
*
* All the methods in this class are invoked in a lazy fashion, meaning that computations are only
* started once the method gets invoked.
*
* @param the graph vertex type.
* @param the graph edge type.
*
* @author Timofey Chudakov
*/
public class ChordalGraphColoring
implements VertexColoringAlgorithm
{
private final Graph graph;
private final ChordalityInspector chordalityInspector;
private Coloring coloring;
/**
* Creates a new ChordalGraphColoring instance. The {@link ChordalityInspector} used in this
* implementation uses the default {@link MaximumCardinalityIterator} iterator.
*
* @param graph graph
*/
public ChordalGraphColoring(Graph graph)
{
this(graph, ChordalityInspector.IterationOrder.MCS);
}
/**
* Creates a new ChordalGraphColoring instance. The {@link ChordalityInspector} used in this
* implementation uses either the {@link MaximumCardinalityIterator} iterator or the
* {@link LexBreadthFirstIterator} iterator, depending on the parameter {@code iterationOrder}.
*
* @param graph graph
* @param iterationOrder constant which defines iterator to be used by the
* {@code ChordalityInspector} in this implementation.
*/
public ChordalGraphColoring(
Graph graph, ChordalityInspector.IterationOrder iterationOrder)
{
this.graph = Objects.requireNonNull(graph);
chordalityInspector = new ChordalityInspector<>(graph, iterationOrder);
}
/**
* Lazily computes the coloring of the graph.
*/
private void lazyComputeColoring()
{
if (coloring == null && chordalityInspector.isChordal()) {
List perfectEliminationOrder = chordalityInspector.getPerfectEliminationOrder();
Map vertexColoring =
CollectionUtil.newHashMapWithExpectedSize(perfectEliminationOrder.size());
Map vertexInOrder = getVertexInOrder(perfectEliminationOrder);
for (V vertex : perfectEliminationOrder) {
Set predecessors = getPredecessors(vertexInOrder, vertex);
Set predecessorColors =
CollectionUtil.newHashSetWithExpectedSize(predecessors.size());
predecessors.forEach(v -> predecessorColors.add(vertexColoring.get(v)));
// find the minimum unused color in the set of predecessors
int minUnusedColor = 0;
while (predecessorColors.contains(minUnusedColor)) {
++minUnusedColor;
}
vertexColoring.put(vertex, minUnusedColor);
}
int maxColor = (int) vertexColoring.values().stream().distinct().count();
coloring = new ColoringImpl<>(vertexColoring, maxColor);
}
}
/**
* Returns a map containing vertices from the {@code vertexOrder} mapped to their indices in
* {@code vertexOrder}.
*
* @param vertexOrder a list with vertices.
* @return a mapping of vertices from {@code vertexOrder} to their indices in
* {@code vertexOrder}.
*/
private Map getVertexInOrder(List vertexOrder)
{
Map vertexInOrder =
CollectionUtil.newHashMapWithExpectedSize(vertexOrder.size());
int i = 0;
for (V vertex : vertexOrder) {
vertexInOrder.put(vertex, i++);
}
return vertexInOrder;
}
/**
* Returns the predecessors of {@code vertex} in the order defined by {@code map}. More
* precisely, returns those of {@code vertex}, whose mapped index in {@code map} is less then
* the index of {@code vertex}.
*
* @param vertexInOrder defines the mapping of vertices in {@code graph} to their indices in
* order.
* @param vertex the vertex whose predecessors in order are to be returned.
* @return the predecessors of {@code vertex} in order defines by {@code map}.
*/
private Set getPredecessors(Map vertexInOrder, V vertex)
{
Set predecessors = new HashSet<>();
Integer vertexPosition = vertexInOrder.get(vertex);
Set edges = graph.edgesOf(vertex);
for (E edge : edges) {
V oppositeVertex = Graphs.getOppositeVertex(graph, edge, vertex);
Integer destPosition = vertexInOrder.get(oppositeVertex);
if (destPosition < vertexPosition)
predecessors.add(oppositeVertex);
}
return predecessors;
}
/**
* Returns a minimum vertex
* coloring of the inspected {@code graph}. If the graph isn't chordal, returns null. The
* number of colors used in the coloring equals the chromatic number of the input graph.
*
* @return a coloring of the {@code graph} if it is chordal, null otherwise.
*/
@Override
public Coloring getColoring()
{
lazyComputeColoring();
return coloring;
}
/**
* Returns the
* perfect elimination order used to create the coloring (if one exists). This method
* returns null if the graph is not chordal.
*
* @return the perfect elimination order used to create the coloring, or null if graph is not
* chordal.
*/
public List getPerfectEliminationOrder()
{
return chordalityInspector.getPerfectEliminationOrder();
}
}