org.jgrapht.alg.transform.LineGraphConverter Maven / Gradle / Ivy
/*
* (C) Copyright 2018-2023, by Joris Kinable 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.transform;
import org.jgrapht.*;
import java.util.*;
import java.util.function.*;
/**
* Converter which produces the line graph
* of a given input graph. The line graph of an undirected graph $G$ is another graph $L(G)$ that
* represents the adjacencies between edges of $G$. The line graph of a directed graph $G$ is the
* directed graph $L(G)$ whose vertex set corresponds to the arc set of $G$ and having an arc
* directed from an edge $e_1$ to an edge $e_2$ if in $G$, the head of $e_1$ meets the tail of $e_2$
*
*
* More formally, let $G = (V, E)$ be a graph then its line graph $L(G)$ is such that
*
* - Each vertex of $L(G)$ represents an edge of $G$
* - If $G$ is undirected: two vertices of $L(G)$ are adjacent if and only if their corresponding
* edges share a common endpoint ("are incident") in $G$
* - If $G$ is directed: two vertices of $L(G)$ corresponding to respectively arcs $(u,v)$ and
* $(r,s)$ in $G$ are adjacent if and only if $v=r$.
*
*
*
* @author Joris Kinable
* @author Nikhil Sharma
*
*
* @param vertex type of input graph
* @param edge type of input graph
* @param edge type of target graph
*
*/
public class LineGraphConverter
{
private final Graph graph;
/**
* Line Graph Converter
*
* @param graph graph to be converted. This implementation supports multigraphs and
* pseudographs.
*/
public LineGraphConverter(Graph graph)
{
this.graph = Objects.requireNonNull(graph, "Graph cannot be null");
}
/**
* Constructs a line graph $L(G)$ of the input graph $G(V,E)$. If the input graph is directed,
* the result is a line digraph. The result is stored in the target graph.
*
* @param target target graph
*/
public void convertToLineGraph(final Graph target)
{
this.convertToLineGraph(target, null);
}
/**
* Constructs a line graph of the input graph. If the input graph is directed, the result is a
* line digraph. The result is stored in the target graph. A weight function is provided to set
* edge weights of the line graph edges. Notice that the target graph must be a weighted graph
* for this to work. Recall that in a line graph $L(G)$ of a graph $G(V,E)$ there exists an edge
* $e$ between $e_1\in E$ and $e_2\in E$ if the head of $e_1$ is incident to the tail of $e_2$.
* To determine the weight of $e$ in $L(G)$, the weight function takes as input $e_1$ and $e_2$.
*
*
* Note: a special case arises when graph $G$ contains self-loops. Self-loops (as well as
* multiple edges) simply add additional nodes to line graph $L(G)$. When $G$ is
* directed, a self-loop $e=(v,v)$ in $G$ results in a vertex $e$ in $L(G)$, and in
* addition a self-loop $(e,e)$ in $L(G)$, since, by definition, the head of $e$ in $G$ is
* incident to its own tail. When $G$ is undirected, a self-loop $e=(v,v)$ in $G$
* results in a vertex $e$ in $L(G)$, but no self-loop $(e,e)$ is added to $L(G)$,
* since, by convention, the line graph of an undirected graph is commonly assumed to be a
* simple graph.
*
* @param target target graph
* @param weightFunction weight function
*/
public void convertToLineGraph(
final Graph target, final BiFunction weightFunction)
{
Graphs.addAllVertices(target, graph.edgeSet());
if (graph.getType().isDirected()) {
for (V vertex : graph.vertexSet()) {
for (E e1 : graph.incomingEdgesOf(vertex)) {
for (E e2 : graph.outgoingEdgesOf(vertex)) {
EE edge = target.addEdge(e1, e2);
if (weightFunction != null)
target.setEdgeWeight(edge, weightFunction.apply(e1, e2));
}
}
}
} else { // undirected graph
for (V v : graph.vertexSet()) {
for (E e1 : graph.edgesOf(v)) {
for (E e2 : graph.edgesOf(v)) {
if (e1 != e2) {
EE edge = target.addEdge(e1, e2);
if (weightFunction != null)
target.setEdgeWeight(edge, weightFunction.apply(e1, e2));
}
}
}
}
}
}
}